Note: Difference in application GUI is just that I
took the first screenshot at work, the second at home.
Let the Wizard Guide You
This article came about because I wanted to make an Add-In for Visual Studio
.NET. The Wizard makes this relatively painless. You can find the
wizard under File/New/Project, then under Other Projects/Extensibility
Projects/Visual Studio .NET Add-in. Make sure to check the box that
says "Yes, create a 'Tools' menu item."
Once the wizard is finished, you can then build the add-in and then run the
setup MSI that is included in the new solution. Then when you press F5 to
bring up a debugging session Visual Studio .NET will be launched and in this new
instance, you should be able to see your new add-in under the tools menu.
It should look like the first image at the top of this page (unless you renamed
your project, it will be your project's name in that case).
Creating the Satellite DLL
In order for the IDE to find your new icon, you must embed the bitmap in an
external generic Win32 C DLL. You cannot insert the bitmap into the
assembly containing the Add-in. Why it was done this way, I cannot tell
you.
To build this Win32 satellite DLL, you must add a new project to the add-in
solution. You can do this from File/Add Project/New
Project, then under Visual C++/Win32 Project. In the
window that pops up, click Application Settings and then click DLL
then Finish.
Now find the bitmap you wish to use as your icon and add it to the DLL
project. There are certain restrictions on the bitmap. These are:
- It must be 16 pixels by 16 pixels
- It must be a 16 color bitmap
- The color to use for transparency is Red = 0, Green
= 254, Blue = 0 (RGB=00FE00h)
Note: The bright green that is on the palette by default is not
the correct green.
Now add a resource file to the project. Then in resource view, right-click
on the newly added .rc file and then click Add Resource then Import to insert the bitmap into the
resource file. In the properties panel, change the ID of the bitmap from
"IDB_BITMAP1" to "1" (no quotes). Build the solution.
You now have a satellite DLL with the bitmap embedded.
Associating the Satellite DLL with the Add-in
Now that you have a satellite DLL, you need to tell Visual Studio .NET that
it is there. This is done via the registry. Two values need to be added to
HKEY_CURRENT_USER or
HKEY_LOCAL_MACHINE Software\Microsoft\VisualStudio\7.0\Addins\<AddInName>
(make sure to change the <AddInName> to the actual name of your add-in:
Note: The hive to add these values to depends on if you chose
the option to have it installed so that everyone can use it.
- SatelliteDLLName = NameOfTheDLL.DLL
- SatelliteDLLPath = C:\InstallPathOfTheAddIn
Both of these can be done via the installer that is in the solution.
Just right-click on the deployment solution and go to View/Registry.
To get the installation folder on installation, use [TARGETDIR] as the
value set in the SatelliteDLLPath variable.
The next thing to do is to place the satellite DLL in a special folder
underneath the installation folder. This folder is the <SatelliteDLLPath>\1033.
The 1033 is just the ID number of the English_Language/Sub-language_English_US.
If your system is not a US system you will need to place the satellite DLL in
your localized code number directory.
You can set this directory by right-clicking on the deployment project and
going to View\File System. Then add a directory under Application
Folder, specifying 1033 (or you preferred language directory) as the folder
name. Then you need to add the primary output of the satellite DLL project to
this directory. This can be done via a right-click on the deployment
project and then clicking Add/Project Output, then moving the
primary output of the DLL to the language directory.
A Code Change
Now that the association is done, you need to open the file Connect.cs
in the main add-in project and find the OnConnection
method. In
this method locate the try
/catch
block at the bottom (it should look like this):
try
{
Command command = commands.AddNamedCommand(addInInstance, "MyAddin1", "MyAddin1",
"Executes the command for MyAddin1", true, 59, ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported+(int)
vsCommandStatus.vsCommandStatusEnabled);
CommandBar commandBar = (CommandBar)commandBars["Tools"];
CommandBarControl commandBarControl = command.AddControl(commandBar, 1);
}
catch(System.Exception )
{
}
The important line is:
Command command = commands.AddNamedCommand(addInInstance, "MyAddin1",
"MyAddin1", "Executes the command for MyAddin1", true, 59, ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled);
Change the true
to false
and 59
to 1
.
This tells Visual Studio .NET that the bitmap is not a built in icon, instead
look at the add-in's satellite DLL and load the bitmap with the ID '1'.
Now if you build the project and then reinstall the add-in your icon should
have changed.
Some Gotchas
- If the add-in does not display in the IDE, run the file ReCreateCommands.reg
in the main add-in directory and restart the IDE.
- Also rerunning the installation process seems to fix the same problem
(sometimes).
References
I would like to thank Carlos for his newsgroup posts, where I found a lot of
the answers for my Add-in questions.
Also, I used the MSDN Library for some info; though the MSDN Library seems
lacking in the VS .NET Add-in documentation.