Hack 89. Writing a Visual Studio Add-in
Although the automation model can be more fun
than a barrel of monkeys, add-ins let you really extend the
environment.
In this book, you have
learned about a large number of different add-ins that you can
install to enhance the functionality of Visual Studio. In this hack,
you will learn how to write one of those add-ins. The topic of
writing Visual Studio add-ins can be, and has been, the topic of
entire books, so needless to say, this hack will simply be an
introduction to the topic.
Add-ins are installable extensions to the Visual Studio IDE. Through
add-ins, you can accomplish quite a bit with the IDE. An excellent
example of this is TestDriven.NET [Hack #93], an add-in that really adds
significant functionality to the IDE.
I am not going to attempt anything that grandiose for this hack.
Instead, you will learn how to create a simple add-in that adds an
item to the Tools menu and to the right-click menu that will allow
you to select text and then click the menu item to surround that code
with a try . . . catch block.
12.5.1. Create the Project
To get started, you will first need
to create a new add-in project by going to File New
Project and then selecting the add-in project from Other
Project Extensibility Projects. This dialog is shown in
Figure 12-4.
This launches the Extensibility Wizard shown in Figure 12-5.
Click Next to move to the first screen of the Extensibility Wizard,
shown in Figure 12-6.
In the first screen of the wizard, you choose what language you want
to use to create this add-in. In this example, I will use C#, but you
can also use Visual Basic or Visual C++. After choosing the language,
click Next and you will see the Select an Application Host screen
(shown in Figure 12-7).
On the Select An Application Host screen, you choose what
application hosts you want your add-in to
be compatible with. The choices are the Microsoft
VSMacros IDE and the regular IDE. It is a
good idea to enable your add-in for the VSMacros IDE only if you
think users will really get value out of using your add-in in that
IDE. In this case, the add-in could indeed be useful from the macro
IDE, so I will leave both of these checked.
When you click Next, you will see the name and description screen
shown in Figure 12-8.
In the name and description screen, you get to name your add-in and
provide a brief description of the tool. Clicking Next will show you
the options screen shown in Figure 12-9.
The add-in options screen includes a number of options for how you
want your add-in to work. Here are the options you must decide upon
on this screen:
- Would you like to create UI for the user to interact with your add-in?
This option decides whether a menu item will be added to the Tools
menu. Having this button on the Tools menu does not mean that you
will need to create a complex UI by any means. In this example, I am
going to check this box because I want users to be able to click a
button in the Tools menu to insert a TRy...catch
block.
- My add-in will never put up modal UI
This option decides whether your add-in can be used during
command-line builds [Hack #78] . You
need to check this box only if your add-in will never show a modal UI
and if your add-in would benefit from being loaded during such a
build. Since this add-in is strictly a coding add-in, I will leave
this box unchecked.
- I would like my add-in to load when the host application starts
This option decides if the add-in will be automatically loaded. This
can always be configured and changed by the user, so I am going to
uncheck it. There is no reason to force the user to load the add-in
every time.
- Setting up access privileges
This option determines whether the add-in will be available to all
users or just the user who installs the add-in. Unfortunately, the
install program does not ask the user to make this choice during the
install process so it is usually a good idea to leave this unchecked.
After you have configured the add-in options for your add-in, you can
click Next to be shown the help about screen, which is shown in Figure 12-10.
The help about screen lets you configure
whether an About box should be enabled for your add-in and, if so,
what should be included in that box. When you click Next, you will
see the Summary screen shown in Figure 12-11.
After completing the wizard, you will see two projects in
the Solution Explorer, a class library and a setup project. You will
also notice a file called
Connect.cs, as shown in Figure 12-12.
Visual Studio also adds a great deal of the boilerplate code to the
Connect.cs file for you. If you open it, you
will see all of the required methods already created with default
code. You could actually run this add-in already, and it would handle
the command�it just wouldn't do
anything.
12.5.2. Add Menu Item
Since you checked the Tools menu option in the
project wizard, Visual Studio will have already added the command for
your add-in to the Tools menu, but you usually want to also have a
menu item somewhere else. In this example, I want to have a menu item
also on the right-click menu. To do this, you will need to modify the
default code that the wizard generated.
When your add-in is loaded, Visual Studio calls the
OnConnection method�this is where you will
need to add commands. Here is the default code created by the wizard:
public void OnConnection(object application,
Extensibility.ext_ConnectMode connectMode,
object addInInst, ref System.Array custom)
{
applicationObject = (_DTE)application;
addInInstance = (AddIn)addInInst;
if(connectMode = = Extensibility.ext_ConnectMode.ext_cm_UISetup)
{
object [ ]contextGUIDS = new object[ ] { };
Commands commands = applicationObject.Commands;
_CommandBars commandBars = applicationObject.CommandBars;
try
{
Command command = commands.AddNamedCommand(addInInstance,
"TryCatchMatic", "TryCatchMatic",
"Executes the command for TryCatchMatic", true,
59, ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported
+(int)vsCommandStatus.vsCommandStatusEnabled);
CommandBar commandBar = (CommandBar)commandBars["Tools"];
CommandBarControl commandBarControl =
command.AddControl(commandBar, 1);
}
catch(System.Exception /*e*/)
{
}
}
}
The boldfaced code is the section that actually creates the command
and then adds it to the Tools command bar. Using the same
Command object, I am also going to add it to the
Code Window command bar, which represents the right-click menu when
inside the code window. First, you need to create a
CommandBar object and get a reference to the
correct command bar, then add your command to that command bar using
the AddControl method. You should insert these two
lines after the last line within the TRy block:
CommandBar commandBar2 = (CommandBar)commandBars["Code Window"];
CommandBarControl commandBarControl2 =
command.AddControl(commandBar2, 1);
This command will now show up on the Tools menu as well as the
right-click menu in the code window after the add-in is installed.
For information on how to find the various command bars in Visual
Studio, please refer to [Hack #90].
You will most likely also want to add something to the
catch block, since the code created by the wizard
simply "swallows" the error. You
can write the exception using Debug.WriteLine or
implement some other method of handling the exception.
12.5.3. Write the Code
The next step is to write the code that
will do the work of the add-in. In this example, I will be writing a
simple piece of code that surrounds the selected text with a
try . . . catch block. This code needs to be added
to the Exec method that was added for you by the
wizard. Here is a look at the default code:
public void Exec(string commandName,
EnvDTE.vsCommandExecOption executeOption,
ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption = =
EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName = = "TryCatchMatic.Connect.TryCatchMatic")
{
handled = true;
return;
}
}
}
This code first checks the executeOptions and then
checks to see if the command being called is the command for this
add-in. Inside the last if statement is where you
will write the code for what your add-in will actually do. Here is
the code I have added to get the currently selected text and then
surround it with a try...catch block:
if(commandName = = "TryCatchMatic.Connect.TryCatchMatic")
{
string selectedText = textDoc.Selection.Text;
string newText = "try\n { \n" + selectedText
+ "\n}\ncatch\n{\n}";
textDoc.Selection.Text = newText;
handled = true;
return;
}
In this code, I get a reference to the
ActiveDocument and then get the selected text. I
can then replace the selected text with the new, surrounded text.
12.5.4. Installation
When you
are ready to install and test your add-in, it is pretty simple to do
so, since the wizard automatically added an installer to the project.
|
Before doing anything else, it is of the utmost importance that you
exclude any assemblies that are default Visual Studio assemblies.
This could include Extensibility.dll,
Office.dll, VSLang.dll,
DTE.OLB, EnvDTE.DLL,
stdole.DLL, and others. If you leave these assemblies in
your installation project, then when a user uninstalls your add-in,
it could remove these assemblies, thus breaking Visual Studio and
requiring the user to either repair her installation or manually try
to re-add the assemblies your installer removed.
|
|
Next, you will need to build the installer, as it is not built by
default. You can do this by right-clicking on the project and
clicking Build. After the project has been built, you can right-click
on the installer and click Install. This will install your add-in on
your machine. Next, you will need to close and then reopen the IDE,
and you should see your menu items. If you do not see your menu
items, make sure that your add-in is enabled in the add-in manager
and then try running devenv
/setup [Hack #92] .
This hack has been a quick introduction to the development of
add-ins, but there is a lot more to learn. Here are some great
resources to help you learn more about add-in development:
- Visual Studio Extensibility Center
http://msdn.microsoft.com/vstudio/extend
- Visual Studio .NET Add-ins Yahoo Group
http://groups.yahoo.com/group/vsnetaddin
- Visual Studio 2003 Automation Samples
http://www.microsoft.com/downloads/details.aspx?familyid=3ff9c915-30e5-430e-95b3-621dccd25150&displaylang=en
- Craig Skibo's weblog (Developer of the Visual Studio Automation Object Model)
http://blogs.msdn.com/craigskibo
- Dr. Extensibility's weblog
http://blogs.msdn.com/dr._ex
|
No comments:
Post a Comment