Working with events

Visual Studio Extensibility Cookbook

Here’s a collection of small code samples on different ways to listen to events.

IVsRunningDocTableEvents Interface

Implements methods that fire in response to changes to documents in the Running Document Table (RDT).

Microsoft docs: IVsRunningDocTableEvents Interface

IVsRunningDocTableEvents Code Samples

You must have a using statement for:

using Microsoft.VisualStudio.Shell.Interop;

In the class where you want to handle the events you must implement the interface: IVsRunningDocTableEvents

internal class Pane : ToolWindowPane, IVsRunningDocTableEvents
{
...
}

OnAfterFirstDocumentLock

OnAfterFirstDocumentLock is called after application of the first lock of the specified type to the specified document in the Running Document Table (RDT).

public:
 int OnAfterFirstDocumentLock(unsigned int docCookie, unsigned int dwRDTLockType, unsigned int dwReadLocksRemaining, unsigned int dwEditLocksRemaining);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnAfterFirstDocumentLock([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie, [In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSRDTFLAGS")] uint dwRDTLockType, [In][ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")] uint dwReadLocksRemaining, [In][ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")] uint dwEditLocksRemaining);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        try
        {
            var activeItem = await VS.Solutions.GetActiveItemAsync();
            if (activeItem != null)
            {
                //Your code here.
            }
        }
        catch (Exception)
        {
            //Your exception code here.
        }
    }).FireAndForget();
    return VSConstants.S_OK;
}

OnBeforeLastDocumentUnlock

OnBeforeLastDocumentUnlock is called before releasing the last lock of the specified type on the specified document in the Running Document Table (RDT).

public:
 int OnBeforeLastDocumentUnlock(unsigned int docCookie, unsigned int dwRDTLockType, unsigned int dwReadLocksRemaining, unsigned int dwEditLocksRemaining);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnBeforeLastDocumentUnlock([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie, [In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSRDTFLAGS")] uint dwRDTLockType, [In][ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")] uint dwReadLocksRemaining, [In][ComAliasName("Microsoft.VisualStudio.OLE.Interop.DWORD")] uint dwEditLocksRemaining);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        try
        {
            var activeItem = await VS.Solutions.GetActiveItemAsync();
            if (activeItem != null)
            {
                //Your coe here.
            }
        }
        catch (Exception)
        {
            //Your exception code here.
        }
    }).FireAndForget();
    return VSConstants.S_OK;
}

OnAfterSave

OnAfterSave is called after saving a document in the Running Document Table (RDT).

public:
 int OnAfterSave(unsigned int docCookie);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnAfterSave([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnAfterSave(uint docCookie)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        try
        {
            var activeItem = await VS.Solutions.GetActiveItemAsync();
            if (activeItem != null)
            {
                //Your code here.
            }
        }
        catch (Exception)
        { 
            //Your exception code here.
        }
    }).FireAndForget();

    return VSConstants.S_OK;
}

OnAfterAttributeChange

OnAfterAttributeChange is called after a change in an attribute of a document in the Running Document Table (RDT).

public:
 int OnAfterAttributeChange(unsigned int docCookie, unsigned int grfAttribs);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnAfterAttributeChange([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie, [In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSRDTATTRIB")] uint grfAttribs);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnAfterAttributeChange(uint docCookie, uint grfAttribs)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        try
        {
            var activeItem = await VS.Solutions.GetActiveItemAsync();
            if (activeItem != null)
            {
                //Your code here.
            }
        }
        catch (Exception)
        {
            //Your exception code here.
        }
    }).FireAndForget();

    return VSConstants.S_OK;
}

OnBeforeDocumentWindowShow

OnBeforeDocumentWindowShow is called before displaying a document window.

public:
 int OnBeforeDocumentWindowShow(unsigned int docCookie, int fFirstShow, Microsoft::VisualStudio::Shell::Interop::IVsWindowFrame ^ pFrame);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnBeforeDocumentWindowShow([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie, [In][ComAliasName("Microsoft.VisualStudio.OLE.Interop.BOOL")] int fFirstShow, [In][MarshalAs(UnmanagedType.Interface)] IVsWindowFrame pFrame);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
        var activeItem = await VS.Solutions.GetActiveItemAsync();
        win = VsShellUtilities.GetWindowObject(pFrame);
        string currentFilePath = win.Document.Path;
        string currentFileTitle = win.Document.Name;
        string currentFileFullPath = System.IO.Path.Combine(currentFilePath, currentFileTitle);
        if (pFrame != null && currentFileTitle.EndsWith(Constants.LinqExt))
        {
            ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                Project project = await VS.Solutions.GetActiveProjectAsync();
                if (project != null)
                {
                    XDocument xdoc = XDocument.Load(project.FullPath);
                    try
                    {
                        xdoc = RemoveEmptyItemGroupNode(xdoc);
                        xdoc.Save(project.FullPath);
                        await project.SaveAsync();
                        xdoc = XDocument.Load(project.FullPath);
                    }
                    catch (Exception)
                    { }
                    if (ItemGroupExists(xdoc, Constants.ProjectItemGroup, Constants.ProjectCompile))
                    {
                        try
                        {
                            if (CompileItemExists(xdoc, currentFileTitle))
                            {
                                xdoc = UpdateItemGroupItem(xdoc, currentFileTitle, currentFileFullPath);
                            }
                            else if (ItemGroupExists(xdoc, Constants.ProjectItemGroup, Constants.ProjectNone))
                            {
                                try
                                {
                                    if (NoneCompileItemExists(xdoc, currentFileTitle))
                                    {
                                        xdoc = UpdateItemGroupItem(xdoc, currentFileTitle, currentFileFullPath);
                                    }
                                    else
                                    {
                                        xdoc = CreateNewCompileItem(xdoc, currentFileFullPath);
                                    }
                                    xdoc.Save(project.FullPath);
                                    await project.SaveAsync();
                                    xdoc = XDocument.Load(project.FullPath);
                                }
                                catch (Exception)
                                { }
                            }
                            else
                            {
                                xdoc = CreateNewCompileItem(xdoc, currentFileFullPath);
                            }
                            xdoc.Save(project.FullPath);
                            await project.SaveAsync();
                            xdoc = XDocument.Load(project.FullPath);
                        }
                        catch (Exception)
                        { }
                    }
                    else if (ItemGroupExists(xdoc, Constants.ProjectItemGroup, Constants.ProjectNone))
                    {
                        try
                        {
                            if (NoneCompileItemExists(xdoc, currentFileTitle))
                            {
                                xdoc = UpdateItemGroupItem(xdoc, currentFileTitle, currentFileFullPath);
                            }
                            else
                            {
                                xdoc = CreateNewCompileItem(xdoc, currentFileFullPath);
                            }
                            xdoc.Save(project.FullPath);
                            await project.SaveAsync();
                            xdoc = XDocument.Load(project.FullPath);
                        }
                        catch (Exception)
                        { }
                    }
                    else
                    {
                        xdoc = CreateNewItemGroup(xdoc, currentFileFullPath);
                        xdoc.Save(project.FullPath);
                        await project.SaveAsync();
                    }
                }
            }).FireAndForget();
        }
    }).FireAndForget();
    return VSConstants.S_OK;
}

OnAfterDocumentWindowHide

OnAfterDocumentWindowHide is called after a document window is placed in the Hide state.

public:
 int OnAfterDocumentWindowHide(unsigned int docCookie, Microsoft::VisualStudio::Shell::Interop::IVsWindowFrame ^ pFrame);
[MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)]
int OnAfterDocumentWindowHide([In][ComAliasName("Microsoft.VisualStudio.Shell.Interop.VSCOOKIE")] uint docCookie, [In][MarshalAs(UnmanagedType.Interface)] IVsWindowFrame pFrame);

Code Sample from: Walkthrough-Create-Language-Editor

public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
{
    ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
    {
        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
        try
        {
            var activeItem = await VS.Solutions.GetActiveItemAsync();
            if (activeItem != null)
            {
                //(LinqToolWindowControl)this.Content).LinqlistBox.Items.Add($"OnAfterDocumentWindowHide: {activeItem.Name}");
            }
        }
        catch (Exception)
        { }
        try
        {
            var win = VsShellUtilities.GetWindowObject(pFrame);
            if (win != null)
            {
                //((LinqToolWindowControl)this.Content).LinqlistBox.Items.Add($"OnAfterDocumentWindowHide: {win.Caption}");
            }
        }
        catch (Exception)
        { }
        win = VsShellUtilities.GetWindowObject(pFrame);
        if (pFrame != null && win.Caption.EndsWith(Constants.LinqExt))
        {
            ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                Project project = await VS.Solutions.GetActiveProjectAsync();
                if (project != null)
                {
                    XDocument xdoc = XDocument.Load(project.FullPath);
                    try
                    {
                        xdoc = RemoveCompileItem(xdoc, win.Caption);
                        xdoc.Save(project.FullPath);
                    }
                    catch (Exception)
                    { }
                    try
                    {
                        xdoc = RemoveEmptyItemGroupNode(xdoc);
                        xdoc.Save(project.FullPath);
                    }
                    catch (Exception)
                    {
                    }
                    xdoc.Save(project.FullPath);
                    await project.SaveAsync();
                }
            }).FireAndForget();
        }
    }).FireAndForget();
    return VSConstants.S_OK;
}
Last updated: