How to: Respond to Events in a Specific Project (Visual C#)

The automation model includes objects that can be used to respond to environment events in the Visual Studio integrated development environment (IDE). The environment events defined in VSLangProj and VSLangProj80 are specific to Visual C# and Visual Basic projects. For example, ImportsEvents is raised when an import is added to, or removed from a Visual Basic project.

This example uses Visual C# to add a ReferencesEvents event handler, which is specific to a type of project, to an add-in project. ReferencesEvents are raised when a reference is changed, added to, or removed from a Visual C# or Visual Basic project.

Note

The dialog boxes and menu commands you see might differ from those described in Help depending on your active settings or edition. These procedures were developed with the General Development Settings active. To change your settings, choose Import and Export Settings on the Tools menu. For more information, see Visual Studio Settings.

  1. Create a Visual Studio add-in project in Visual C#.

  2. Add using VSLangProj; to the top of the Connect.cs file.

  3. On the Project menu, click Add Reference, click the .NET tab, select the first VSLangProj and click OK.

  4. In the Connect class, initialize a variable to handle the ReferencesEvents object and another to handle an OutputWindowPane.

        private DTE2 _applicationObject;
        private AddIn _addInInstance;
        private VSLangProj.ReferencesEvents refEvents; 
        private OutputWindowPane outputWinPane;
    

    In this example, the variable is named refEvents.

    Other objects in the automation model relate to other types of events that are specific to the project. For example, ImportsEvents is raised when an import is added to or removed from an Imports collection. BuildManagerEvents applies to events related to temporary assemblies built from outputs of custom tools. For more information on BuildManager object, see Introduction to the BuildManager Object. For a complete list of the events that are specific to types of projects, see Event Objects (Specific to Types of Projects), and for a list of the general automation events, see Automation Event Objects.

  5. In the OnConnection method, initialize a variable to intercept events. In this example, the variable is called events.

    EnvDTE80.Events2 events = 
    (EnvDTE80.Events2)_applicationObject.Events;
    
  6. In the OnConnection method, initialize an OutputWindow variable.

    OutputWindow outputWindow = (OutputWindow)_applicationObject.Windows.Item
    (Constants.vsWindowKindOutput).Object;
    outputWinPane = outputWindow.OutputWindowPanes.Add
    ("ReferencesEvents Event Information");
    
  7. Also in the OnConnection method, retrieve the event objects from the automation model.

    refEvents = 
    (VSLangProj.ReferencesEvents)events.GetObject
    ("CSharpReferencesEvents");
    

    In this example the ReferencesEvents are specific to Visual C# projects. To respond to Visual Basic specific events, replace the string, CSharpReferencesEvents,with VBReferencesEvents. For more information about how to determine the strings to use for events that are specific to different types of projects, see Event Objects (Specific to Types of Projects).

  8. Connect to each delegate exposed from the event objects retrieved in step 3 by using the += operator. For example, to connect the delegates exposed by the ReferenceAdded event, you would use:

    refEvents.ReferenceAdded += new 
    _dispReferencesEvents_ReferenceAddedEventHandler
    (this.ReferenceAdded);
    
  9. Add procedures for each event that is related to the event object. For example, to handle the event that occurs when a reference is added, you would use:

    public void ReferenceAdded( VSLangProj.Reference addedRef ) 
    { 
        outputWinPane.OutputString( "ReferencesEvents.ReferenceAdded" 
    + "\n" ); 
        outputWinPane.OutputString( "The reference to " + addedRef.Name
     + " was added." + "\n" ); 
    }
    

    In the case of ReferencesEvents, you must have events defined for:

    and

    The complete listing of the example below includes these events.

  10. Finally, to prevent Visual Studio from slowing your system by continuing to monitor window-related events after you close the add-in, you should disable event handling. In Visual C# this is done by using the -= operator. For example, to disable event handling for the ReferenceAdded you would use:

    refEvents.ReferenceAdded -= new
     _dispReferencesEvents_ReferenceAddedEventHandler
    (this.ReferenceAdded);
    

    This turns off event handling whether the add-in or the IDE is shut down while the add-in is still running. When the IDE is shut down, all running add-ins are automatically shut down first.

Example

The following example is a basic Visual Studio add-in that demonstrates how to intercept and handle Visual C# reference events in Visual Studio. Whenever a reference event occurs, a notification message is sent to the Output window.

using System;
using Microsoft.VisualStudio.CommandBars;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using VSLangProj;

public Connect()
  {
  }
  public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
  {
    _applicationObject = (DTE2)application;
    _addInInstance = (AddIn)addInInst;

    // Retrieve the event objects from the automation model.
    EnvDTE80.Events2 events = 
(EnvDTE80.Events2)_applicationObject.Events;
    // Send event messages to the Output window.
    OutputWindow outputWindow =
 (OutputWindow)_applicationObject.Windows.Item
(Constants.vsWindowKindOutput).Object;
    outputWinPane = 
outputWindow.OutputWindowPanes.Add
("ReferencesEvents Event Information");

    // Retrieve the event objects from the automation model.
    refEvents = (VSLangProj.ReferencesEvents)
events.GetObject("CSharpReferencesEvents");

    // Connect to each delegate exposed from each object 
    // retrieved above.
    refEvents.ReferenceAdded += new
 _dispReferencesEvents_ReferenceAddedEventHandler
(this.ReferenceAdded);
    refEvents.ReferenceChanged += new
 _dispReferencesEvents_ReferenceChangedEventHandler
(this.ReferenceChanged);
    refEvents.ReferenceRemoved += new
 _dispReferencesEvents_ReferenceRemovedEventHandler
(this.ReferenceRemoved); 
  }

  public void OnDisconnection(Extensibility.ext_DisconnectMode
 disconnectMode, ref System.Array custom)
  {
    // If the delegate handlers have been connected, then 
    // disconnect them here. 
    // If you do not do this, the handlers may still 
    // fire because they have not been garbage collected.
    if (refEvents != null)
    {
        refEvents.ReferenceAdded -= new
 _dispReferencesEvents_ReferenceAddedEventHandler
(this.ReferenceAdded);
        refEvents.ReferenceChanged -= new
 _dispReferencesEvents_ReferenceChangedEventHandler
(this.ReferenceChanged);
        refEvents.ReferenceRemoved -= new
 _dispReferencesEvents_ReferenceRemovedEventHandler
(this.ReferenceRemoved); 
    }
  }

  // References related events.
  public void ReferenceRemoved( VSLangProj.Reference removedRef ) 
  { 
    outputWinPane.OutputString( "ReferencesEvents.ReferenceRemoved"
 + "\n" ); 
    outputWinPane.OutputString( "The reference to " + removedRef.Name
 + " was removed." + "\n" ); 
  } 

  public void ReferenceChanged( VSLangProj.Reference changedRef ) 
  { 
    outputWinPane.OutputString( "ReferencesEvents.ReferenceChanged" 
+ "\n" ); 
    outputWinPane.OutputString( "The reference to " + changedRef.Name 
+ " was changed." + "\n" ); 
  } 
        
  public void ReferenceAdded( VSLangProj.Reference addedRef ) 
  { 
    outputWinPane.OutputString( "ReferencesEvents.ReferenceAdded" +
 "\n" ); 
    outputWinPane.OutputString( "The reference to " + addedRef.Name 
+ " was added." + "\n" ); 
  } 
  public void OnAddInsUpdate(ref System.Array custom)
  {
  }
  public void OnStartupComplete(ref System.Array custom)
  {
  }
  public void OnBeginShutdown(ref System.Array custom)
  {
  }
  private DTE2 _applicationObject;
  private AddIn _addInInstance;
  private VSLangProj.ReferencesEvents refEvents;
  private OutputWindowPane outputWinPane;
  }}

Compiling the Code

To compile this code, create a new Visual Studio add-in project in Visual C# and replace the code of the Connect class with the code in the example. For information about how to run an add-in, see How to: Control Add-Ins By Using the Add-In Manager.

See Also

Tasks

How to: Respond to Events in a Specific Project (Visual Basic)

Reference

+= Operator (C# Reference)

-= Operator (C# Reference)

Other Resources

Responding to Automation Events

Responding to Events (Visual Basic and Visual C# Projects)