Automation and Extensibility Overview
Visual Studio Team
Summary: This paper introduces the Microsoft® Visual Studio® .NET Automation model and shows you how you can use it to build tools to enhance your development experience. (16 printed pages)
Automation and the Visual Studio .NET Automation Model
Visual Studio .NET Automation Object Model Chart
The Spectrum of Visual Studio .NET Automation
Accessing the Automation Model
Exposing and Accessing Add-Ins and Wizards
Although Visual Studio .NET offers developers many tools and the power to accomplish almost every task, some developers require an additional or finer level of control. For example, they might have a task or series of tasks that they find they are performing regularly and would like to automate. To address this issue, Visual Studio .NET features a rich programming model for extending and automating its IDE (integrated development environment) known as the Automation model. The Automation model provides the ability to automate the environment and provide extensions and new features to it.
This article is an overview of Visual Studio .NET Automation features. Future articles will provide more in-depth, detailed procedures for programming against the various parts of the model, as well as how to use the model to accomplish different tasks.
To view the documentation on the Visual Studio .NET Automation model, search the index for "IDE, ways to manipulate," or see Manipulating the Development Environment under the Developing with Visual Studio .NET.
In the past, the Visual Studio .NET Automation object model was known as the "extensibility model," but extensibility is an overloaded term that can mean automation, External Tools (on the Tools menu), Tools/Options, command bar customization, or macros. The Visual Studio .NET Automation model allows you to programmatically control and extend the IDE. This object model is included with Visual Studio .NET and is publicly documented. Another way to programmatically extend the IDE is by joining Visual Studio Integrator Program (VSIP), which is described in The Spectrum of Visual Studio .NET Automation.
What is the Visual Studio .NET Automation model?
The Visual Studio .NET IDE consists of several interrelated tool windows, such as the Toolbox and the Task List, and document windows such as Solution Explorer and the Code Editor. The Automation model in Visual Studio .NET contains the programmatic objects and interfaces in the IDE that allow you, as a developer, to programmatically control and automate these windows as well as other IDE functionality such as solution and project build configurations, code editing, and debugging. Using the Automation model, you can create VSMacros, add-ins, and wizards to automate tasks, manipulate aspects of the IDE, and respond to IDE events.
Some examples of the objects and interfaces are:
- The Tasklist object represents the Task List.
- The Toolbox object represents the Toolbox.
- The ToolboxTab object represents a tab in the Toolbox.
- The ToolboxItem object represents an item in the Toolbox.
Some objects are collections of other objects; that is, they either contain or reference multiple identical objects. For example, the ToolboxTabs collection contains one or more ToolboxTab objects, each representing a tab displayed in the Toolbox. The ToolboxItems collection contains one or more ToolboxItem objects, each representing an item under a Toolbox tab.
The Visual Studio .NET automation model is a composite of several sub-models, each one covering a major area of functionality. It is important to note that although divisions are shown here, the core environment model and all of the sub-models are common across, and available to, all Visual Studio .NET languages.
|Core environment model||This comprises the majority of the Visual Studio .NET automation model. It includes objects to control IDE elements (that is, tool and document windows, commands, menus, and so forth), events, and IDE functionality.
Nearly all of the Visual Studio .NET Automation model is common across all Visual Studio .NET languages. Some additional objects are available for projects and for the Microsoft® Visual C++® .NET code model.
|Project model||Includes both common and language-specific objects for controlling solutions, projects, and project items. Common solution/project objects work with any Visual Studio .NET project, whereas language-specific project objects are designed to work only with a specific Visual Studio .NET language.
The project model is common across all Visual Studio .NET languages. Visual C++ .NET provides some additional extensions that are specific to that language.
|Editor model||Includes objects to manipulate the text in the Code Editor such as inserting and deleting code, formatting and moving code around, setting bookmarks, and so forth.
The editor model is common across all Visual Studio .NET languages.
|Code model||Includes objects to discover code and project items and manipulate code definitions. This model exposes the classes, interfaces, structs, and so forth, and members of those types.
The code model is common across all Visual Studio .NET languages. Visual C++ ® .NET provides some additional extensions specific to that language.
|Forms model||Includes objects to control Windows Forms and form properties, but not Web forms.
The forms model is common across all Visual Studio .NET languages.
|Debugger model||Includes objects to control the Visual Studio .NET debugger.
The debugger model is common across all Visual Studio .NET languages.
|Build model||Includes objects to control solution and project build operations and configurations. Allows you to programmatically set debug options and create automated or unattended builds.
The build model is common across all Visual Studio .NET languages.
Each of these sub-models contains objects that relate to a specific UI element or functionality of Visual Studio .NET. For example, the Core Environment model — which contains groups of related objects and collections common to all Visual Studio .NET programming languages — has objects that allow you to manipulate the Toolbox, the Task List, code displaying in the Code Editor, and so forth. The Debugger model contains groups of related objects that allow you to control aspects of debugging, such as breakpoints, processes, threads, stackframes, and so forth.
Although the Visual Studio .NET Automation model is composed of sub-models, the entire model itself is programmatically seamless and there are no boundaries between the various models, other than the fact that some models, such as the Forms model, are contained in separate type libraries or assemblies.
The following link leads you to a hierarchical overview chart of the entire Visual Studio .NET Automation model: Automation Object Model Chart.
Visual Studio .NET offers three different ways to access the Automation model:
- Visual Studio .NET Macros (VSMacros)
- Add-ins and wizards
- Visual Studio Integrator Program (VSIP)
VSMacros are the easiest way to automate and extend the IDE with code. Not only do they provide a big productivity boost by allowing you to record several actions in the IDE and play them back as a single command, they can also be used as a tool to learn the Visual Studio .NET Automation Model. VSMacros are created using a separate, full-featured development environment called the VSMacros IDE that is based on the Visual Studio .NET IDE. It uses the Microsoft Visual Basic® .NET language and is custom-made for VSMacro editing and debugging. For more information about VSMacros, see Automating Repetitive Actions by Using Macros and Macros Development Environment.
Add-Ins and Wizards
Add-Ins are time- and labor-saving applications that attach to and are used within the IDE. They are COM objects that implement the IDTExtensibility2 Interface and communicate with the IDE through the Visual Studio .NET Automation model. Most programming languages offer additional automation objects through their own type libraries. These libraries are outlined in Accessing the Automation Model.
Unlike macros, add-ins are compiled, binary code, so your intellectual property is protected. You can implement add-ins in any COM-consuming language such as Visual C++ .NET, Visual Basic .NET, Visual C# .NET, and so forth.
For most developers, VSMacros are sufficient for programming against the Visual Studio .NET Automation model. In some cases, though, add-ins can be preferable for developers such as ISVs who want to seamlessly add entire new features to the IDE. Add-Ins fit such features seamlessly into the Visual Studio .NET IDE as though they were built in.
Add-ins also allow you to do a few other things that VSMacros cannot. Using add-ins, you can:
- Create custom property pages for the Options dialog box on the Tools menu. For more information, see Controlling Tools Options Settings.
- Create tool windows that act just like Visual Studio .NET tool windows. For more information, see Creating and Controlling Tool Windows.
- Dynamically enable and disable commands on menus and Command bars. For more information, see Adding and Handling Commands.
- Add contact and descriptive information to the Visual Studio .NET Help About box.
For more information about add-ins, see Creating Add-Ins.
Wizards are a series of automated steps that help a user accomplish programming tasks that are more difficult or complicated than usual. For example, Visual Studio .NET offers the Add-In wizard to help users create an add-in project and deployment project. You can create your own wizards for users by building a COM object that implements the IDTWizard interface. Wizards are typically invoked through the New Project or New File dialog boxes. For more information about wizards, see Creating Wizards.
Visual Studio Integration Program (VSIP)
For the majority of Visual Studio .NET users, VSMacros, add-ins, and wizards meet most of their needs. Some ISVs, however, need to go beyond the considerable capabilities of the Visual Studio Automation model. For example, a user might want to incorporate a new programming language into the Visual Studio .NET IDE, possibly creating a need for:
- A new project type.
- A customized editor.
- Advanced debugging features.
The Visual Studio Integration Program, or VSIP, was created so you can accomplish this. VSIP provides you with the tools and information you need to integrate your products into the Visual Studio .NET environment. VSIP, which is a collection of SDKs, is a developer suite and platform that gives VSIP partners finer and more extensive control over the environment by providing access to more interfaces and full Visual Studio .NET Help integration. With VSIP, partners are able to provide greater functionality in their users' IDE. For more details about VSIP, see http://msdn.microsoft.com/vstudio/vsip/default.asp.
Choosing the Appropriate Automation Approach
If you are unsure of which way to integrate new functionality into the IDE, consider the following factors.
Do you want to distribute the code or a compiled application?
- Distribute the code - you can use a VSMacro. You can deploy VSMacros by copying their project files to the new location. There is no setup or registration, but users of your macro must use the Load Macro Project command on the Macros submenu on the Tool menu to start using the macros. For additional information, see Recording Macros.
- Distribute a compiled application - use either an add-in or a wizard. Add-ins and wizards protect your intellectual property through compilation, but have the additional overhead of a deployment project, or some other form of setup, such as registering the add-In or wizard and copying the .vsz files to the correction location for wizards.
What programming language do you want to use to develop your automation application?
- Visual Basic - You can create VSMacros, add-ins, or wizards.
- Other programming languages - You can create add-ins and wizards using the IDTExtensibility2 Interface and the IDTWizard Interface. You must be able to implement a CoCreate-able COM object in the programming language.
Does the task require user input?
- No user input is needed - A VSMacro or add-in is appropriate.
- Simple input - A VSMacro, add-in, or wizard is appropriate.
- Complex input - If the input has several steps or requires verification, a wizard is usually best. If you need to put UI in a tool window, however, an add-in is required.
How complicated is the task you are automating?
- Simple - If a task can be accomplished with only a few lines of code, a VSMacro is appropriate.
- Complicated - While VSMacros can include forms, references, and classes, an add-in or wizard might be more appropriate.
How do you think your user will start your application?
- Menus, command bars, or key bindings - You can use an add-in or VSMacro.
- A keyboard shortcut or the Macro Explorer - You can use a VSMacro.
- New Project or New Item dialog box - Using a wizard is typical for adding a new project or file to an application.
What is the lifetime of your application?
- I need it just for today - A recorded VSMacro might be sufficient.
- I will be using it long-term - The VSMacro, wizard, and add-in are all appropriate.
What do you need to develop?
- An automated task - VSMacros, add-ins, and wizards can all be used to automate tasks.
- Custom property pages for the Tools, Options dialog box - Add-ins support this functionality.
- Custom tool or document windows - Add-ins support this functionality.
- A new project type - Become a VSIP partner.
- Support for a new programming language in .NET or a new editor - Become a VSIP partner.
The majority of the Visual Studio .NET Automation model is contained in a .NET assembly called "EnvDTE." (The COM+ component type library [typelib] version is called "Microsoft Developer Environment 7.0.") This assembly/typelib contains all of the previously mentioned sub-models with the exception of the Forms model, which is contained in System.Windows.Forms. Additional assemblies support language-specific automation functionality. The following is a list of other typelibs that relate to automation and extensibility:
|.NET Assembly / Namespace Name||COM Typelib Name||Description|
|EnvDTE||Microsoft Development Environment 7.0||Contains objects for the core automation/extensibility models, such as IDE, editor, code, build, and debug.|
|VSLangProj||Microsoft Visual Studio .NET VB and C# Project-specific Model||Contains objects relating to the project object model specific to Visual Basic .NET and Visual C#® .NET. These are extensions to the common project model.|
|Microsoft.VisualStudio.VCCodeModel||Microsoft Development Environment Visual C++ .NET Code Model 7.0||Contains objects relating to the Visual C++ .NET code model. These are extensions to the common code model.|
|Microsoft.VisualStudio.VCProject||Microsoft Development Environment Visual C++ .NET Project System Engine 7.0||Contains objects relating to the Visual C++ .NET project model. These are extensions to the common project model.|
|Microsoft.VisualStudio.VCProjectEngine||Microsoft Development Environment Visual C++ .NET Project System Engine 7.0||Contains objects relating to the Visual C++ .NET project model.|
|Microsoft.VisualStudio.VSWizard||VCWiz 1.0 Type Library||Contains the objects that relate the Visual C++ .NET Wizard model.|
To gain access to the contents of an assembly or typelib (from Visual Basic .NET or from Visual C# .NET), you must first reference it in your project. This is done by choosing Add Reference on the Project menu, or by right-clicking the References node in Solution Explorer and choosing Add Reference, and then selecting the assembly/typelib that you want to reference. The names appear under two different tabs: one for .NET assemblies, the other for COM+ components. For Visual C++ .NET and typelib references, you use #include.
Note When you create an add-in using the Add-In wizard, the EnvDTE typelib, among others, is automatically referenced for your convenience.
For most situations, set your references to .NET assemblies. If you set a reference to a COM component, you are, in essence, setting a reference to a .NET assembly. The reason is, when you set a reference to a COM object, Visual Studio .NET "wraps" the COM component by generating a metadata assembly, and the actual reference goes to that assembly rather than to the original COM object.
After you reference the required assemblies or typelibs, you gain access to their objects, interfaces, collections, and members. You can examine the objects and members available to you in the typelib or .NET assembly using the Object Browser. To display the Object Browser, press CTRL+ALT+J, or choose Object Browser on the View menu. Expand the EnvDTE node (or other node) to view the available objects and members.
Hierarchical Access to Objects
As with most other object models, objects in the Visual Studio .NET Automation model are hierarchically accessed. That is, to programmatically use an object, you must use its full hierarchical reference. For example, the StatusBar object is located hierarchically in the Automation model as:
Figure 2. The StatusBar Object
The top-most object in the EnvDTE typelib is the DTE object, which represents the Visual Studio .NET IDE. DTE and dteObject are pre-defined global variables in VSMacro projects. Both DTE and dteObject are passed into an Add-In through IDTExtensibility2::OnConnection or IDTWizard::Execute.
In the Visual Studio .NET Automation model hierarchy, the StatusBar object is immediately subordinate to the DTE object, as shown in the previous diagram. Therefore, to programmatically reference the StatusBar object in Visual Basic .NET, you would use:
Sub SBarTest() Dim objSBar As StatusBar objSBar = DTE.StatusBar objSBar.Text = "Hello" End Sub
The same example for Visual C++ .NET would be (assumes var dteObject):
EnvDTE.StatusBar objSBar; objSBar = dteObject.StatusBar; objSBar.Text = "Hello";
The same hierarchy rules apply, with slight modifications, when you refer to tool windows such as the Task List, Toolbox, Solution Explorer, and so forth. In the case of a tool window, you refer to it using its pre-defined window type constant and indexing the Windows collection. For example, to refer to the Task List, use:
Dim win As Window = DTE.Windows.Item(Constants.vsWindowKindTaskList) Dim objTL As TaskList = win.Object
A number of automation-related samples are available to you on the Visual Studio .NET Automation Sample Web site at: http://msdn.microsoft.com/vstudio/downloads/samples/automation.aspx. Examining this code is a great way to learn how to program against the Automation model. In addition to the samples, many of the language reference topics in Visual Studio .NET have short example code snippets associated with them.
Visual Studio .NET contains a project wizard for creating add-ins. It is located in the Extensibility Projects folder under the Other Projects folder in the New Project dialog box. You can choose to create either a Visual Studio .NET add-in or a Shared add-in. The difference is that a Shared add-in can be used either in Visual Studio .NET or in Microsoft Office applications such as Microsoft Word, Excel, PowerPoint, and so forth, whereas a Visual Studio .NET add-in is designed to work only with Visual Studio .NET and VSMacros.
Selecting either kind of add-in starts the Add-In wizard. The Add-In wizard creates an add-in with a skeletal, albeit fully functional framework that you can run immediately after you finish creating it. After asking you the language in which you want to implement your add-in, the Add-In wizard generates a basic framework that you can add code to and customize.
The Add-In wizard lets you supply a display name and description for the add-in, both of which will appear in the Add-In Manager dialog box. For details about the options on a panel, click its Help button. In addition, you can choose to have the wizard generate code that adds a command to the Tools menu to load and invoke the add-in in the Visual Studio .NET IDE.
When you finish the wizard, you have a new project with a single module that implements the add-in. You also have a setup project that builds an .msi file that can be used to install the add-in on another system (or to update the registration of the add-in on the development machine, as is sometimes necessary depending on what you do with your add-in).
Add-ins consist of:
- The add-in project.
- A connection class — implements all of the IDTExtensibility2 methods. The primary method to implement is
- Inside the connection class, there is code to expose the add-in to the end-user, such as code to add a button to a toolbar.
- Add-in registration — performed automatically for you when you use the Add-In wizard and build the project. If you add more commands or change the name of any commands the add-in offers, then you must build the deployment project and run the resultant .msi file while Visual Studio .NET is not running in order for the update to occur.
The Add-In wizard also creates a setup project so that you can distribute your add-in later if you wish. For information about setup projects, search for "Setup projects" in the Visual Studio .NET Help index. When you create an add-in on your system by using the Add-In wizard, the wizard sets all of the necessary registry keys up on your system. For others to use your add-in on their systems, however, they must run the setup project for the add-in to create the necessary registry keys on their system.
To create an add-in using the Add-In wizard
- Create a new Visual Studio Add-In project. You can find this project type in the Extensibility Projects folder under Other Projects.
- Select one of the languages from the Select a Programming Language panel. This determines the language in which the add-in will be generated. The choice of language is up to you — choose the one with which you feel most comfortable.
- Choose one or more applications, such as Visual Studio .NET, from the Select an Application Host panel. This allows you to select the applications in which you want to be able to run the add-in after its creation.
- Enter the name and description for your add-in in the Enter a Name and Description panel. This name will later display in the Available Add-Ins list of the Add-In Manager dialog and inform users what the add-in does, how it works, and so forth.
- In the Choose Add-In Options panel, specify whether you want the add-in to appear in the Tools menu, when you want the add-in to start, and whether or not the add-in will be available to others, or only to the user that installs the add-in. This allows you to specify certain behavior options for your add-in.
- In the Choosing Help About Information panel, specify whether you want the add-in mentioned in the Help About box, and if you do, specify the information you want it to display. This allows you to create a Help About window for your add-in that displays version information, support information, licensing information, and so forth. After following steps 1-6, the options you selected are displayed in a summary page.
- Choose Finish to create the add-in.
You now have a fully functional, empty add-in. To enable the add-in to do something useful, you must add the appropriate code. To learn about what the Add-In wizard does behind the scenes, examine the deployment project it creates, the OnConnection method, and the IDTCommandTarget::Exec method.
Once an add-in is created, it must be registered as a COM component with Microsoft Windows. The Add-In wizard automatically performs this registration for you on the development machine.
For information about how to manually register add-ins or to find out the registry keys affected by the Add-In wizard, search the Visual Studio .NET index for "add-ins" and then "registering" to view the Help topic "Add-In Registration."
Using Windows Forms in Tool Windows
Currently, when you want to use a Windows Form in a tool window, you must use a special shim control. You can create tool windows only with ActiveX controls or Document Objects. The shim control is simply an ActiveX control that hosts a Windows Form object. This will be covered in more detail in a later article; the basics are presented here.
The shim control is available free of charge on the Visual Studio .NET Automation Sample Web site: http://msdn.microsoft.com/vstudio/nextgen/automation.asp.
To use the shim control to create a tool window in Visual C# .NET
- In your add-in, add a User control (in this case, called "HostUserControl"). This User control is what you will later add to the tool window. The control can be in a separate assembly, but the code below defaults to the assembly of the add-in.
- Add the following code to your add-in:
object objTemp = null; EnvDTE.Window windowToolWindow = applicationObject.Windows. _ CreateToolWindow (addInInstance, "VSUserControlHost. _ VSUserControlHostCtl", "C# Tool window", guidstr, ref objTemp); windowToolWindow.Visible = true; VSUserControlHostLib.IVSUserControlHostCtl objControl = _ (VSUserControlHostLib.IVSUserControlHostCtl)objTemp; objControl.HostUserControl(System.Reflection.Assembly. _ GetExecutingAssembly().Location, "ControlClassHere");
- Change the text
ControlClassHerein the last line of code to the full name of the Windows Form class to use.
windowToolWindow.Visible = true is called before calling HostUserControl. Otherwise, the User control will appear in the top-left of your monitor and parented to (that is, associated with) the desktop. You can hide the window after that, but that line must be there.
Persisting State for Add-Ins, VSMacros, and Wizards
Normally, when you create variables and assign values to them in a project or add-in or wizard, the values are lost when the solution or add-in is unloaded or the IDE is shut down. The Visual Studio .NET Automation model provides an object known as the Globals object that allows automation clients to persist, or store, the values of variables. You can save the state information you want in the solution file, a project file, or on a per-user/per-machine basis in the application data.
For details and examples about how to use the Globals object to persist variable data, search the Visual Studio .NET Help index for "Globals object" and then select "Persisting Information in Projects and Solutions" in the Index Results window.
Wizards, such as the Add-In wizard, are a type of automation client that leads a user step-by-step through a series of actions to accomplish a complex or difficult task and, once completed, go away. Wizards are created by implementing the IDTWizard interface and have only one method, Execute, which contains the code you want the wizard to run. A wizard can be programmed to create a fully working application for the user, or a skeletal application that the user needs to add additional code to for it work correctly, such as with the Add-In wizard.
For additional information about creating wizards using the Visual C++ .NET HTML-Style wizard, see "custom wizards, designing" and "custom wizards, creating" in the Visual Studio .NET Help index.
Although wizards can be constructed to appear any way you like, they usually consist of one or more windows, or panels. Panels can contain a descriptive image, such as in the top or left side of the panel, a label description, instructions, and an area in which navigation controls such as Next, Previous, and Cancel can be placed.
Figure 3. Example of a Wizard
The wizard, when completed, can be made available as a template in the New Project and New File dialog boxes.
To create a wizard
- Create a new Class Library project in the Visual Studio .NET language of your choice.
- In the class module, implement the IDTWizard interface. For example, in Visual Basic® .NET:
- Create the Execute procedure. You can do this using the drop-down combo boxes in the Visual Basic .NET Code Editor. Execute is the method called when a wizard is first activated.
- Add the code you want to the Execute method of the IDTWizard, as well as any other code you want.
- Compile the project. If you used Visual Basic .NET or Visual C# .NET, this creates a .NET Framework assembly.
- If you create a Visual Basic .NET or Visual C# .NET wizard, you must register the component by using regasm, unless you check the "Register for COM Interop" checkbox under the Configuration/Build node in the property page of the project. When this is done, the wizard is automatically registered when the project is built on the developer's machine.
- Create a .vsz file for the wizard. This makes it appear in the New Project or New File dialog boxes. For more information, see VSZ Files.
Note You can also create an optional VSDir file for the wizard. A VSDir file contains the information that displays as a description for the wizard in the New Project or New File dialog boxes, and it allows you to specify an icon and arrange its location in the list. For more information, see "VSDir Files" later in this article.
At this point, you can run the wizard by choosing Project on the New submenu on the File menu and then navigating to the new wizard in the New Project dialog box.
To display a custom icon for the new wizard, either specify a path to the icon (.ico) file in the VSDir file or place an icon file in the same directory as the wizard file with the same base filename as the .vsz file, but with an .ico extension. For example, if the wizard is called MyWizard.dll, you would name the .ico file MyWizard.ico.
Visual Studio .NET uses a file type called .vsz to launch wizards. These files are text files with a .vsz extension that Visual Studio uses to determine the wizard to call and the custom information to pass to it, if any.
A .vsz file is essentially a simplified version of an .ini format text file, except that it has no labeled sections. The first part stores information known to the Visual Studio environment, and the second section allows parameters specific to the wizard to be collected by the environment and passed to the wizard.
The following is an example of a sample .vsz file:
VSWizard 7.0 Wizard=VIDWizard.CBlankSiteWizard Param=<item1> Param=<item2>
It has these parts:
- VSWizard — This is the version number of the template file format, which for Visual Studio .NET is "VSWizard 7.0" or "VSWizard 6.0." Using any other number results in an "Invalid format" error.
- Wizard — This is either the ProgID or string representation of the CLSID of the wizard to be co-created by Visual Studio. If using a GUID, it follows the format <8>-<4>-<4>-<4>-<12>.
- Param — These parameters are optional and you can add as many as your add-in requires. They are used to allow the .vsz file to pass additional custom parameters into the wizard. Each value is passed as a string element in an array of variants to the wizard. Custom parameters allow you to have one wizard COM object, but launch it in different ways, for example, preset some options or not show some steps or panels.
Optionally, you can create a VSDir file to position your wizard in the dialog boxes. A VSDir file is a text file with a .vsdir extension that provides information to the Add Item and New Project dialog boxes about how to display its items, such as their names, the order in which they appear, and the icon displayed with them. You can have multiple VSDir files in a single directory, but typically, a single VSDir file contains records for multiple wizards, folders, and templates. A newline character separates each record in the file and vertical bar (|) characters separate the fields in each record. Any optional field for which there is no meaningful data should contain two vertical bars next to each other with no intervening characters.
For an example of a VSDir file as well as details about each field, see VSDir Files in the Visual Studio .NET product documentation.
Once you create an add-in or wizard, you need a way to expose it to users so that it can be run. You can use one or more of the following methods:
- Add-In Manager — The Add-In Manager dialog box (displayed by selecting Add-In Manager on the Tools menu) displays all add-ins registered with Visual Studio .NET. Using this dialog box, you can immediately load or unload add-ins in the IDE as well as specify its behavior and command line options, if applicable.
- Menus — Using options in the Add-In wizard, or in the code the add-in project created for you, you can specify whether or not the add-in has a command added to the Tools menu, and whether or not the IDE automatically loads the add-in when the end-user invokes the command. If you select this option, a command is created and placed on the Tools menu and a placeholder image appears on the toolbar.
- Toolbars — Using the CommandBar object, you can add a button to a Visual Studio .NET toolbar that, when clicked, activates your add-in. As mentioned previously, the Add-In wizard also offers an option that, when selected, does this for you. If you want to see how the Add-In wizard accomplishes this, you can view the code for the Add-In wizard on the Automation Samples Web site: http://msdn.microsoft.com/vstudio/downloads/samples/automation.aspx.
- IDE Startup / System Events — Using the Add-In Manager, you can specify that your add-in starts when the IDE starts. Using the Events object and the various other event objects, such as ProjectsEvents, SolutionsEvents, OutputWindowEvents, DebuggerEvents, and so forth, you can connect the activation of your add-in to a system event. The add-in loads when the IDE starts, but it does not do anything until one of the events it is associated with occurs. For an example of how to respond to IDE events, see the EventWatcher add-in sample on the MSDN Automation Samples Web site at: http://msdn.microsoft.com/vstudio/downloads/samples/automation.aspx.
Commands Issue When Developing Add-Ins
When you create an add-in by using the Add-In wizard and then run it, another instance of Visual Studio .NET starts, allowing you to test and debug the resultant add-in. One or more commands for the add-in are placed on one or more menus, such as the Tools menu. When you finish debugging the add-in and then close this second instance of Visual Studio .NET, the command information is saved.
When you close the first instance of Visual Studio .NET, however, the command information that was written by the second instance of Visual Studio .NET is overwritten. The effect is that when you restart Visual Studio .NET, your new add-in command no longer appears on the menu. There is a procedure you can follow, however, to restore the commands to the menu.
To restore add-in commands to the menu
- Build the setup project created by the wizard.
- Shut down all instances of Visual Studio .NET.
- Execute the .msi file from the setup project.
- Restart Visual Studio .NET.
From now on, when you run Visual Studio .NET, the add-in commands will be present on the menus.
Note The setup project will build and install faster if you modify it to exclude the .NET Runtime re-distributable merge module.
Debugging an add-in requires two instances of Visual Studio .NET. The code for the add-in is opened in the first IDE instance and the add-in itself is hosted in the second IDE instance. As you control the add-in from the second instance, any errors encountered are reflected in the first instance.
Figure 4. Debugging Add-Ins
The first instance also allows you to perform normal debugging tasks such as setting breakpoints, watch variables, and so forth.
There is an issue with persisting toolbar buttons or commands when creating and/or debugging add-ins. For details, see "Add-In Commands Issue" in Exposing and Accessing Add-Ins and Wizards.
In this article, you learned about the features of the Visual Studio .NET Automation model. You also learned about VSMacros, add-ins, and wizards, and about how to create and use them.
Visual Studio .NET Automation is a powerful tool for you to automate, customize, and extend the IDE, and leverage your work. It allows you to truly customize the IDE to match your exact needs and save precious development time and effort.