In the previous posts we created small VSPackages with the help of the Visual Studio Integration Package wizard without any coding. In Part #5 we treated a few VSX ideas, looked into VSPackages and treated the pattern how packages can provide and consume services. In this post we make a few steps toward.
If you want to create more complex packages than we did in former posts — and if you are reading this post I am sure you want — it is a good idea first to solve simple common tasks that can help us later.
In this post we start creating a toolset (types, methods and patterns) to help us creating “easy-to-write-and-understand” code. I plan this activity to span at least three posts with the following topics:
Prolog: We create the first part of our sample package to be the base of our toolset creation. In this post we are going to add menu commands manually and discover command table configuration files.
Finishing the sample: W e create the second part of our base sample. In this post we add a custom tool window to our package by hand and discover output windows.
Refactoring cycle: We modify our sample package while extracting useful utility types to reuse in package development.
In this sample application we are going to create a tool window that allows simple arithmetic operations between two integer numbers:

This series of posts is not about functionality but rather about the steps to get to the sample application. By creating a simple toolset allows us to develop packages easier than simply using the VS SDK interop assemblies and MPF types. I am going to tell you these in the Refactoring cycle post.
Create an empty VSPackage
We start creating our toolset with an empty VSPackage. In the previous posts I illustrated the steps how to create an empty package, this time I will omit the majority of screenshots.
So we start with a new Visual Studio Integration Package project that will bring up the well-known (he is now our close friendJ) VSPackage wizard. Let’s name our project to StartupToolset. Set the programming language to C# and set the basic information according to the following picture:

On the next wizard page let the Menu command, Tool window and Command editor checkboxes unchecked; on the page after uncheck both test project types and click on Finish. The wizard creates the source for an empty project. Run it and check in the Help|About box that the StartupToolset package registers itself correctly with the VS Experimental Hive.
(At this point I cleaned the wizard-generated code from comments, to make the code shorter and readable in this post. You can do the same, but before deleting the comments it is worth to read and understand them, mainly in the StartupToolsetPackage.cs file. These comments give you excellent hints to understand the code.)
In the previous posts we added menu commands and tool windows to the package using the VSPackage wizard. To see all the steps required for these activities, in this example we will add the menu command and the tool window to the package manually and I also explain you why activities are important.
Add a new menu item manually
To show up a menu item we have the following TODO list:
1. Create an ID, a name and a display text for the command that will show up the tool window.
2. Create a .vsct file to set up the so-called command table configuration for the menu command item.
3. Add the ProvideMenu attribute to the package class
4. Set up the compilation options of the .vsct file
5. Create the menu item handler method
6. Associate the command with the handler method
What is the command table configuration file?
In the previous post I mentioned that VSPackages are on-demand loaded, the IDE loads them into the memory when their objects are about to be created or any of their services is are about to be used. It sounds good, but there is an issue to solve: If the objects representing menus and toolbars of the VSPackage are compiled into the package code, the IDE actually needs to load the package into the memory in order to extract code for the UI. The IDE even needs to do it if the package is not used, only to display menu and toolbar items in VS. To allow displaying the package related menu and toolbar items, those are represented as a binary resource in the package. When the package is registered (by regpkg.exe) these resources are extracted, stored separately and later Visual Studio can display them without loading the package binary.
The command table configuration file is the key for this operation. This file’s role is to define the UI related to commands. When we compile a package, the command table configuration file is translated into a binary command table output file (called .cto file) and actually this file is added to the package binary as a byte array resource.
In the VS 2005 versions of Visual Studio SDK used a textual format (using files with .ctc extension). Editing and understanding a.ctc file is not a simple task. With the release of Visual Studio 2008 SDK Microsoft created new XML-based file format (.vsct: Visual Studio Command Table) and a new compiler called to produce the binary .cto format.
The main advantage of using the .vsct file is that it is editable just like other XML files and so has all the great XML editing features like automatic generation of closing tags, or IntelliSense based on the .vsct XML schema. Due to the fact XML format has so many advantage the old .ctc format has been deprecated. Microsoft recommends using the VSCT compiler to generate the .cto files, although CTC is still supported.
Step 1: Adding a command ID
This activity is required to distinguish the command item represented by other commands defined in Visual Studio or in other VSPackages. Commands are uniquely identified UI-related objects just like menu items or bitmaps. IDs of UI-related objects are hierarchical represented by a pair of a GUID and a 32 bit unsigned integer. The GUID represents a logical container the object belongs to and the 32 bit unsigned integer the distinguishing ID of the object within that logical container.
The wizard creates a Guids.cs file for us containing one GUID representing the package and another one representing a so-called command set for the commands of the package:
...
static class GuidList
{
public const string guidStartupToolsetPkgString =
"1376bfe2-5278-493d-867e-2b5ba828368d";
public const string guidStartupToolsetCmdSetString =
"ec3d3ea6-2261-4a18-a458-78591688e06d";
...
};
Our menu item to display the custom tool window is an item in the logical container of the command set, so we need a 32 bit ID within the container. We place this ID as a constant into a new file named PkgCmdID.cs. We use this file name as a convention. The VSPackage wizard uses the same name if it creates a command ID. So, let’s create and fill PkgCmdID.cs:
namespace MyCompany.StartupToolset
{
static class PkgCmdIDList
{
public const uint cmdidCalculateTool = 0x101;
};
}
Step 2: Setting up the .vsct file
The .vsct file represents the command table configuration, it has an XML format. To display the menu item we must set up a .vsct file that defines all user objects and resources required to display it and bind it to the code that performs the related action.
In a future post I am going to treat the format and usage of the .vsct file in a very detailed form, but right now I give you only a short overview.
Because we created an empty package, the VSPackage wizard did not create any command table file for us. Let’s add the StartupToolset.vsct file by ourselves with the Add New Item function where we select the XML file template. Set the content of the file to the following:
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns=
"http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<Extern href="stdidcmd.h" mce_href="stdidcmd.h"/>
<Extern href="vsshlids.h" mce_href="vsshlids.h"/>
<Extern href="msobtnid.h" mce_href="msobtnid.h"/>
<Commands package="guidStartupToolsetPkg">
<Buttons>
<Button guid="guidStartupToolsetCmdSet" id="cmdidCalculateTool"
priority="0x0100" type="Button">
<Parent guid="guidSHLMainMenu" id="IDG_VS_WNDO_OTRWNDWS1"/>
<Icon guid="guidImage" id="bmpPic1" />
<Strings>
<CommandName>cmdidCalculateTool</CommandName>
<ButtonText>Calculate Tool Window</ButtonText>
</Strings>
</Button>
</Buttons>
<Bitmaps>
<Bitmap guid="guidImage" href="Resources\Clock.bmp" mce_href="Resources\Clock.bmp" usedList="bmpPic1"/>
</Bitmaps>
</Commands>
<Symbols>
<GuidSymbol name="guidStartupToolsetPkg"
value="{1376bfe2-5278-493d-867e-2b5ba828368d}" />
<GuidSymbol name="guidStartupToolsetCmdSet"
value="{ec3d3ea6-2261-4a18-a458-78591688e06d}">
<IDSymbol name="cmdidCalculateTool" value="0x0101" />
</GuidSymbol>
<GuidSymbol name="guidImage" value="{91CB158E-29BC-4818-8C1F-967AF94D96B1}" >
<IDSymbol name="bmpPic1" value="1" />
</GuidSymbol>
</Symbols>
</CommandTable>
The root element of the .vsct file is the CommandTable element. The opening tag sets up its current namespace and as we can see, the .vsct file has a schema.
As I mentioned before, objects are identified by GUIDs and (GUID, unsigned int) pairs. In the command table we must refer to IDs used in Visual Studio. The Extern element in the CommandTable allows loading (include) those IDs from header files. In this command table we use the following header files:
| File |
Content |
| stdidcmd.h |
This file represents the command IDs for all commands exposed by Visual Studio. IDs include the visible (or hidden) menu command IDs prefixed with cmdid, standard editor commands with ECMD_ prefix and a few others.
|
| vsshlids.h |
This files collects command IDs for the menus provided by the Visual Studio shell. As command IDs use GUID, in this file we find many definitions prefixed with guid. The unsigned int parts of command IDs are represented in this file with IDM_VS, IDG_VS and a few other prefixes.
|
| msobtnid.h |
This file represents IDs of commands within Microsoft Office.
|
The header files can be found in under the VS 2008 SDK root folder in the VisualStudioIntegration\Common\Inc directory and its subfolders.
Our package defines its own GUIDs and command IDs. We (may) refer to these IDs within the .vsct file one or more times. To make the definition simpler and free of mistyped IDs, We have a Symbols element in the command table to allow define symbolic names for GUIDs and command IDs:
<Symbols>
<GuidSymbol name="guidStartupToolsetPkg"
value="{1376bfe2-5278-493d-867e-2b5ba828368d}" />
<GuidSymbol name="guidStartupToolsetCmdSet"
value="{ec3d3ea6-2261-4a18-a458-78591688e06d}">
<IDSymbol name="cmdidCalculateTool" value="0x0101" />
</GuidSymbol>
<GuidSymbol name="guidImage" value="{91CB158E-29BC-4818-8C1F-967AF94D96B1}" >
<IDSymbol name="bmpPic1" value="1" />
</GuidSymbol>
</Symbols>
We use the symbol names instead of their values, like in the following example:
<Bitmap guid="guidImage" href="Resources\Clock.bmp" mce_href="Resources\Clock.bmp" usedList="bmpPic1"/>
As you can see, GuidSymbol elements (IDs for logical containers) can have IDSymbol elements (id IDs of elements within the container).
Now, we have enough to set and use object IDs. It’s time to look for the object definitions.
As .vsct represents commands, the Commands element encloses all definitions. As we know from previous posts, all commands belong to an owning VSPackage. The package attribute identifies this VSPackage:
<Commands package="guidStartupToolsetPkg">
...
</Commands>
The Commands element includes child elements like Groups, Buttons, Bitmaps, etc. to define “ingredients” of a command definition. For example, if we have a menu of related commands then the menu is defined by a Group element within Groups, menu items by Button elements within Buttons and related bitmaps in the Bitmaps section.
In our .vsct we have the following definition for our single menu item:
<Buttons>
<Button guid="guidStartupToolsetCmdSet" id="cmdidCalculateTool"
priority="0x0100" type="Button">
<Parent guid="guidSHLMainMenu" id="IDG_VS_WNDO_OTRWNDWS1"/>
<Icon guid="guidImage" id="bmpPic1" />
<Strings>
<CommandName>cmdidCalculateTool</CommandName>
<ButtonText>Calculate Tool Window</ButtonText>
</Strings>
</Button>
</Buttons>
We defined one menu item having a type of Button and the ID as a pair of the related guid and id with the corresponding values in the Symbol section. Button has a few child nodes representing the properties of the menu item:
| Element |
Description |
| Parent |
Item that acts as a parent of this Button representing a command. A Button can have one or more Parent elements, as the represented command can be placed into one or more location. For example, it can be put on the main menu, on several toolbars and on contexts menus at the same time.
In this concrete example the guidSHLMainMenu identifies the main menu of Visual Studio as the logical container of the parent, IDG_VS_WNDO_OTRWNDWS1 is the ID for the View|Other Windows item.
|
| Icon |
Defines the icon to be displayed for the command.
|
| Strings\CommandName |
Declares the name of the command. It can be used to search for the command by its name.
|
| Strings\ButtonText |
Display text of the command.
|
Let’s see how the icon (or bitmap) of the command is defined:
<Bitmaps>
<Bitmap guid="guidImage" href="Resources\Clock.bmp" mce_href="Resources\Clock.bmp" usedList="bmpPic1"/>
</Bitmaps>
The definition of icons, images and other bitmaps is within the Bitmaps element where one Bitmap node declares a bitmap strip. The guid attribute defines the ID of the bitmap strip, href tells the physical location relative to the project folder. The usedList attribute is a comma separated enumeration of strip IDs within the bitmap strip to be used. These IDs are defined in the Symbols section as IDSymbol child nodes of the GuidSymbol representing the bitmap. Bitmap strip IDs are one-based. When we use a bitmap in the strip, we use this ID from the usedList.
Step 3: Add the ProvideMenu attribute to the package class
To ensure that regpkg.exe registers our menu resources we must decorate our package class with the ProvideMenu attribute. This attribute names the resource holding the menu and command information and provides an attribute to set the menu version. In order to achieve the required behavior we add the following attribute to the package class:
...
[ProvideMenuResource(1000, 1)]
public sealed class StartupToolsetPackage: Package { ... }
...
Why we use just the value of 1000 as the resource ID? You will get the answer soon...
Step 4: Setting up the compilation options for the .vsct file
At the beginning of this post where I treated the role of Command Table Configuration file I mentioned that the .vsct file is compiled into a binary resource. When we added the StartupToolset.vsct file to our project, its Build Action has been set to None:

To compile the command table file into the binary resource, the Build Action should be set to VSCTCompile (when we use the VSPackage wizard, it sets the Build Action to it).
Here is the point when we have issues with Visual Studio (or more correctly with the first release of Visual Studio 2008 SDK). When you want to set the Build Action to VSCTCompile you will not find that on the list of possible actions! If you type it by hand, you’ll get in Invalid Property error. That is what you call a “feature” that actually means BUG.
To solve this issue I have found several workarounds. The most stable (and straightforward) is to modify the .csproj file by hand.
Open it with a text editor (e.g. Notepad) and look for the StartupToolset.vsct file. You will find it in an item group with None build action:
<ItemGroup>
<None Include="StartupToolset.vsct" />
</ItemGroup>
Change the highlighted node with the following one:
<ItemGroup>
<VSCTCompile Include="StartupToolset.vsct">
<ResourceName>1000</ResourceName>
</VSCTCompile>
</ItemGroup>
The VSCTCompile element will set the correct build action. The ResourceName child node will cause the build process to embed the binary .cto file into your VSPackage with the resource ID of 1000. It is required to ensure that regpkg.exe will register our package’s menu correctly when using the default ProvideMenuResource attribute:
...
[ProvideMenuResource(1000, 1)]
public sealed class StartupToolsetPackage: Package { ... }
...
Step 5: Creating the command handler method
Right now we do not have a tool window to show up with our newly created menu function, so instead of a tool window we are going to display a message. We add a private event handler method to the StartupToolsetPackage class:
...
public sealed class StartupToolsetPackage : Package
{
...
private void ShowCalculateToolCallback(object sender, EventArgs e)
{
MessageBox.Show("Calculate Tool Window is about to be displayed...",
"Tool Window");
}
...
}
Step 6: Associating the event handler with the command
We use the same patter as we did in our previous samples (SimpleCommand and SimpleToolWindow). The setup code is embedded into the overridden Initialize method of the package class. We use the proper GUID and ID pairs of the menu item in the .vsct file:
protected override void Initialize()
{
Trace.WriteLine(string.Format(CultureInfo.CurrentCulture,
"Entering Initialize() of: {0}", this.ToString()));
base.Initialize();
OleMenuCommandService mcs =
GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs)
{
CommandID menuCommandID = new CommandID(GuidList.guidStartupToolsetCmdSet,
(int)PkgCmdIDList.cmdidCalculateTool);
MenuCommand menuItem = new MenuCommand(ShowCalculateToolCallback,
menuCommandID);
mcs.AddCommand(menuItem);
}
}
Taste the pudding
Completing the steps above we have a package with a manually created menus command that shows up a message box. Compile and run the package! When the Visual Studio 2008 Experimental Hive starts you can discover our menu item in the View|Other Windows submenu:

Click on the Calculate Tool Window item and the expected message box shows up:

Where we are?
We started creating a toolset for programming VSPackages. As one of the first steps, we created an empty package and added a menu command to the package by hand. While we did that, we discovered the Visual Studio Command Table files and their roles in describing UI resources for packages.
When setting up the compilation of .vsct files we have found a bug (feature?) related to the Build Action property. We resolved the issue by manually modifying the .csproj file.
In the next post we are going to create the tool window by hand and adding simple functionality.
Posted
Jan 14 2008, 06:30 PM
by
inovak