VSXL 1 – Tackling commands and menus.
This part will explain how we can reorganize the menus and commands to enable usage of an extension package.
To get around the workings of menus and commands I can recommend this blog by Inovak. Though it is written to build his VSXtra tool, it explains the inner workings of VS in context of menus and commands.
There is another blog by Inovak that explains the vsct file, which is a key part in the menus and commands workings (see below).
Next picture gives an overview of the parts that contribute in the menus and commands, based upon Inovak’s blog items.
Goal
We want the ability to add a (menu) command from a context menu when project is selected.
Let us take a look on what tasks should be automated when we use the current VSX approach:
- Update the vsct file and let the user give input on how and where the menu is displayed
- When dynamic menu, a BeforeQueryStatus eventhandler is needed
- Update the initialize method of the custom ‘Package.cs’ file to add the menucommand to the menucommand service
The first problem here is, there is no physical file for the command. All coding is done in the ‘package.cs’ file. So, let’s try to migrate the code from the package file to a separate command file.
The Command file.
These are the things that are directly related to the command and can be put in a separate class:
- The Id of the command: a uint
- The id of the commandset the command is belonging to : a guid
- The implementation of execution of the command
- [Optional] Visibility handling: via BeforeQueryStatus
Regarding the command id; in the MS solution they are gathered in the ‘PkgCmdId.cs’ file. This is not a bad idea since they are a range of id’s and no guids. For example, 0×100 is the first, 0×101 is the second, and so on. Otherwise, it would be nice to have them tightly coupled to the command file itself. So a reference to the id is the preferable solution.
Regarding the commandset id; in the MS solution they are gathered in the ‘GuidList.cs’ file. Since this is a guid and if we make use of a CommandGroup class as a holder of the id, I don’t see the benefit of using this.
Since a command is bound to its package, a reference to this package is also needed.
The CommandGroup itself is merely a representation of the Id. If we want to query which commands are attached, we can either use the VSCT file or query the Commands in the package that point to a specific CommandGroupClass.
The ‘CustomCommand’ is a set of 2 partial classes. One is generated by our integration package (storing the id’s and reference to the type of CommandGroup), another is presented to the developer to implement the base methods. This is called the double-derived pattern. In that way we can regenerate the custom command without removing the implementation.
A second task is to be done when generating a command class: managing the ‘PkgCmdId.cs’ file. Before loading our integration package command, we could load this class into memory and keep it there for the lifetime of the command execution. It should be presented as a package service so we could call something like ‘CreateNewCmdId(string commandName)’. The management and synchronization should be handled by this service. We’ll tackle this issue in a future blog, which will probably be: tackling the services.
Notice, that to be able to register the command we need to call the IMenuCommandService. Since the called method ‘GetService’ is declared on the Package class, we can only access it from there. For now, we’ll use a utility to retrieve all the Command classes that need to be registered. Likewise, it will be refactored when tackling the services.
A last task is to keep in sync with the VSCT file. We can make use of XDocument to readout and write to. It should not allow making any changes to the command ids. To make things a little bit easier we can make use of the VS internal RDT (running document table). To keep in scope, we’ll dedicate this in a separate blog.
VSCT revised
There are a few things that one could change about the way the VSCT file is used. Since it is only a declarative way of showing the command table definitions, it is possible to handle the building of the resources ourselves and create a resource per command. But this would mean that a custom postbuild tool should be made to create this resource. Since the added value of this is minor, I don’t think it’s a good idea.
On the other hand, creating a custom editor for managing the VSCT file looks like a better idea. Of course, I’m not the only one who thought of that: VSCT PowerToy, available at the MSDN code gallery [http://code.msdn.microsoft.com/VSCTPowerToy]. With this tool you cannot only manage your own command table but also look at other packages’ command tables! It’s a nice way to learn on how to build your own ones.
In the next blog we will show you the coding of this all.


Recent Comments