Tutorial 1: Getting Started with Visual Studio Extensibility
Visual Studio is well known for being a world-class development environment. But Visual Studio is far more than a set of development tools. In addition to providing great tools for developing software, Visual Studio is also an open and extensible platform. For example, if somebody creates a new language, developers can add support within Visual Studio for that language, including the ability to edit code written in that language (both as text and through graphical designers) and compile the code in that language, even if Visual Studio does not support the language by default.
Visual Studio provides many different ways to be extended. You can add new tool windows, new editors, and so on.
You will learn:
- What the different levels of extensibility in Visual Studio are.
- What the Visual Studio extensibility architecture is.
- What the Managed Package Framework is.
- Why you need to run Visual Studio under the experimental hive.
- What the Visual Studio user interface basics for package development are.
Levels of Extensibility in Visual Studio
The Visual Studio SDK provides you with many different ways of extending Visual Studio. The following diagram shows a high-level view of the different levels of extensibility.
The following sections provide more detail on these different levels.
Macros are the easiest way to extend Visual Studio. The Visual Studio IDE includes the Macros IDE, through which you can develop macros written in VB.NET, shown in the following figure.
The Macros IDE looks much like Visual Studio itself; in fact, it uses much of the same architecture and subsystem. You can write VB.NET subroutines and functions, which you can in turn attach to menu items and toolbar buttons in Visual Studio itself; this makes it possible for you to automate common tasks in Visual Studio.
Although macros are easy to use, they are rather limited in what you can accomplish, as they do not have access to the inner workings of Visual Studio; for example, they cannot create tool windows. Also, the source code is not compiled, when you distribute a macro, you distribute all your source code.
To find out more about Visual Studio macros, you can read the documentation on MSDN.
Add-ins are a type of extension to Visual Studio that are self-contained assemblies that can automate Visual Studio tasks in much the same way macros do. Unlike macros, however, add-ins can be written in any language and are compiled. Add-ins have access through the automation system to the tool windows and command system of Visual Studio.
When you program add-ins, you have access to an object called the DTE, which is a root object representing Visual Studio. This object is the root object in the Visual Studio automation model. Through this object, you can access many objects that are a part of Visual Studio. These allow you to manipulate and control Visual Studio. For example, the DTE object includes a property called ActiveDocument, which returns a reference to the document currently being edited. The DTE object also contains a Solution property, which returns an object representing the current solution.
Visual Studio Packages (or VSPackages for short) are the next type of extensions. Like add-ins, these are compiled assemblies. However, unlike add-ins, VSPackages are integrated right into the IDE and loaded as part of the IDE itself. As such, VSPackages have access to much of the core functionality of Visual Studio. Because of the deep integration, VSPackages offer much more power than add-ins.
Although you can use any language you like to build a VSPackage, the two best choices are C++.NET and C#. Additionally, you can use VB.NET; however, the wizards and templates that ship with the Visual Studio SDK do not offer any VB.NET options, only C++.NET and C#. Further, most developers today will want to choose C# over C++.NET, although you are certainly not required to do so.
Visual Studio Extensibility Architecture
Throughout the tutorials in this trail, we will be using VSPackages to extend Visual Studio. VSPackages are just the right mix of power and ease. By using various wizards, you can quickly and easily create an extension to Visual Studio.
In order to use VSPackages, you need to understand the architecture of the extensibility platform. The following diagram shows a high-level view of the architecture.
At the base is the Visual Studio IDE itself, which is what you are extending. The IDE can be controlled through two means, automation and the Package API. Typically the automation approach is used either externally through other software, or through add-ins or macros. VSPackages, however, can make use of the Package API, which is the same API used by the internal Visual Studio teams at Microsoft. This API can be called through C# code. Or, if you're using C++, you can use a template-based library called the Visual Studio Library (VSL). But with the help of .NET Interop Assemblies, you can create managed packages. To simplify such development, you can use the Managed Package Framework.
Managed Package Framework
At the heart of a VSPackage written in C# is a layer called the Managed Package Framework (MPF). This is a framework written on top of the Interop Assemblies, which provides an extremely easy yet powerful method of extending Visual Studio. Using this framework, you can create any number of packages that can extend Visual Studio. For example, you can:
- Create new menus for Visual Studio.
- Add new commands to Visual Studio.
- Create Options pages.
- Integrate with the built-in tool windows, such as the Task List, Error List, and Properties windows.
The tutorials in this trail use this framework.
Additionally, the MPF provides a powerful way of registering your packages with Visual Studio. With the help of a simple command-line utility called regpkg.exe, you can easily register your packages, provided you create a base package class that uses various attributes provided by the MPF. The MPF includes numerous attribute classes that you can attach to your base package class, which take care of the hassles of registration. After you build your package assembly, you run the regpkg.exe utility, which calls code in these attributes that registers your package. Such registration involves creating entries in the system registry, thus integrating your package right into Visual Studio.
Most of the classes and interfaces for the MPF are found in the Microsoft.VisualStudio.Package and Microsoft.VisualStudio.Shell namespaces. The internal objects in Visual Studio often implement numerous interfaces. Instead of obtaining a reference to the object itself, you'll obtain a particular interface from the object in order to manipulate certain aspects of the object.
For example, if you want to manipulate the Task List tool window, you can request the IVsTaskList interface, which allows basic management of the task list, including adding new task providers. If you want to manipulate the individual items in the task list, you can obtain the IVsTaskList2 interface. These two interfaces work with the same object but provide different interfaces into the object; you use whichever one suits your needs.
Further, if you want to receive events from the task list, you'll create an object that implements the IVsTaskListEvents interface. You will then pass a reference to your object into Visual Studio, which will then call into your interface. Thus, the interfaces can work either way with Visual Studio.
Run Visual Studio under the Experimental Hive
To test your VSPackage extensions, you'll run Visual Studio under the experimental hive. This will start Visual Studio but specify a different part of the Windows registry to use for its registration information. By default, when you install the Visual Studio SDK, the installer runs a program called VsRegEx.exe (found in the VisualStudioIntegration\Tools\Bin directory under the SDK's root directory). This program copies over all the Visual Studio registration entries into a new, separate hive of the registry. Then, when you start Visual Studio to test your extension, you specify that it should use this new, separate hive. That way, you can register all your extensions in this separate area, and test them out without causing damage to your "real" installation of Visual Studio. You can even manually run the VsRegEx.exe tool to create more experimental hives, or recreate the main experimental hive.
Find out more information about how to use the VsRegEx.exe tool.
Visual Studio User Interface Basics for Package Development
When you extend Visual Studio through a VSPackage, it's important to be aware of the various parts that make up Visual Studio and which a user of Visual Studio may well take for granted. For example, nearly every Visual Studio user is aware of the various tool windows such as the Solution Explorer and how to move them around and dock them in a manner that's most comfortable. However, what the Visual Studio user might not realize is that these tool windows are each their own specialized window that enables users to interact with a particular aspect of the system, and new tool windows can be added to the system.
Tool windows and other GUI elements
Tool windows are the ubiquitous child windows seen throughout Visual Studio. Such windows typically provide a particular yet often general task, and offer various controls with which the user can interact. For instance, the Properties window allows the user to set properties of objects that serve a particular purpose. The Properties window is specialized in this sense, but also general in that it can be used in many different situations. Similarly, the Output window is specialized in that it provides text-based output, but general in that many subsystems within Visual Studio can use it to provide output to the Visual Studio user.
One other common thread between tool windows is that they do not display documents. Tool windows are not used for editing documents, neither as text editors nor as a drag-and-drop designers. Rather, document editing is handled by document windows, which appear in the tabbed central area of Visual Studio.
Consider the following screen shot of Visual Studio:
You can see a few tool windows. Several of the tool windows are docked on a single pane on the right, with only Solution Explorer showing and the rest accessible through tabs. At the bottom of the window are two other tool windows, the Error List and Output, again both docked on a single pane. In left pane is the main document pane showing several editor windows. Note that although tool windows usually live as a single instance (you can only open a single Solution Explorer, for example), the editor windows can have multiple instances, all docked within the single document pane, and each being used to edit a separate window. This example screen shows two core editor windows, both being used to edit different C# files, one form designer window, and a browser window showing the Start Page. Of these, all are available through tabs, but in this example, only the EditorPane.cs file is visible and active.
When you extend Visual Studio, you can create your own tool windows that allow the Visual Studio users to interact with your extension; and you can create your own editors that allow Visual Studio users to edit documents. Since your tool windows and editors are integrated into Visual Studio, you do not need to worry about how to dock a tool window or make an editor appear within the tabbed document area of Visual Studio. Once you register the windows correctly, they will automatically take on the usual features of tool windows and document windows found in Visual Studio.
As an extension writer interacting with tool windows, you'll need to recognize that each tool window has its own GUID, which allows it to be identified. As you provide through these tutorials, you'll see where you can find these GUIDs and how to access them.
Toolbars and buttons
When you create your own tool window, you can include several GUI elements, including toolbars with elements such as buttons and combo boxes. Note that in Visual Studio, toolbars are considered a type of menu. Thus, as you create your extensions, if you want to specify a toolbar, you create it as a menu. From there, you create a group within the toolbar (or menu) that holds controls. If you're creating an actual menu, the groups are shown as a set of menu items grouped together, typically with horizontal dividers between them. In terms of toolbars, these items are grouped together typically with vertical bars between them.
Just as toolbars are considered a kind of menus, the controls you put on a toolbar or menu are all considered buttons, even if they are, in fact, other elements such as combo boxes.
The reason for this generic view is that you can focus more on what the buttons and menus do, and less on their graphical appearance. As for their appearance, they will automatically take on the overall look and feel of Visual Studio.
When you create GUI elements such as buttons, the buttons themselves are actually a visual representation of a command. You've seen this before in many places. For example, when you customize a toolbar in a product such as Microsoft Word, you add buttons to the toolbar by dragging a command onto the toolbar. This concept is even more prevalent in Visual Studio, where nearly every aspect of its functionality is accessed by the user through the use of commands.
For example, when you click Build/Build Solution, you are using a menu "button" to execute the Build Solution command. You can see this when you right-click one of the main toolbars in Visual Studio and then, in the pop-up menu, click Customize. When the Customize dialog box opens, you can then click the Build menu, which will reveal the menu; however, clicking its items does not cause them to run. You can then right-click the Build Solution menu item to reveal the customization menu, as shown in the following figure.
From there you can change the text that appears in the menu, but you cannot change the command. That's because the button is a visual representation of the command itself (as opposed to a button with a command attached to it). If you want a different command, you need to drag a command from the Customize dialog box onto a menu or toolbar to add a new menu item or button for the command.
Commands can be issued directly in various ways through the IDE. For example, if you right-click the name of the solution in the Solution Explorer, the same Build Solution command is available, this time through a pop-up menu. If you make the Build toolbar visible, the command is again available, this time through a button on a toolbar. Visual Studio even provides a command-line interface right in the IDE through which you can issue commands. You can show this window by clicking the menu View/Other Windows/Command Window.
The Command window (remember, this is another tool window) then opens (by default, in the bottom pane). Commands are grouped by category and can be typed in interactively by typing the category, a dot, then the command. To run the Build Solution command, you type Build.BuildSolution and press ENTER.
Note that when you type the dot after "Build," an IntelliSense window opens showing you the different commands available in Build. (The categories, such as Build, are the same as shown in the left list of the Customize dialog box, but without spaces. For example, the Class Diagram commands are available by typing ClassDiagram without a space.)
When you extend Visual Studio, you can create and add your own commands to the environment. You can then specify how these commands will appear in the IDE. Most often, they will appear either as a menu item in the main Visual Studio menu or in one of the toolbars. Typically you'll place your custom commands on the Tools menu, and you'll place a command for displaying your tool window in View/Other Windows.
The next tutorial is a hands-on walkthrough of creating a Visual Studio extension. The samples in this trail are all VSPackage extensions as they provide much more power than the macros and add-ins, and, thanks to the wizards in the Visual Studio SDK, are quite easy to get started with.