
Professional Visual Studio 2005 (2006) [eng]
.pdf
Chapter 26
Macro projects, modules, and individual macros can all be renamed by right-clicking their entry in the Macro Explorer and choosing Rename. Modules and macros can also be deleted from within this tool window, while macro projects can be unloaded with the same context menu.
Figure 26-1
The Load Macro Project command displays the Add Macro Project dialog in which you can browse the file system for .vsmacros project files. Each one you load will be added to the top level of the tree view.
Figure 26-1 shows the MyMacros project in bold in the Macro Explorer. This is because it has been set as the Recording Project, which is where any temporary macros are placed when you record them. You’ll learn how to record macros later in this chapter.
Running Macros
The most direct method to run a macro is to double-click its entry in the Macro Explorer. You can optionally right-click and select the Run menu command (see Figure 26-2), but given that macros are meant to make the developer’s life easier, this method is rarely used.
Figure 26-2
As the macro is executed, the macro engine will display an icon depicting a cassette tape, and an accompanying tooltip in the system notification area of the Windows taskbar (shown in Figure 26-3).
This information is useful for longer running macros, and can be used to stop the execution of a macro that is behaving in an unexpected way (e.g., stuck in an endless loop). As the tooltip indicates, just double-click the icon to stop the macro’s execution.
346

Macros
Figure 26-3
You can also run macros directly from the command window by entering in the macro name and pressing Enter. However, the easiest way to run macros that you use often is to assign them to keyboard shortcuts. Because Visual Studio uses proper reflection techniques, the Keyboard options page in the Environment section will include any macros that are currently loaded into the IDE (see Figure 26-4).
Figure 26-4
Note that the Show All Settings checkbox at the lower-left corner of the Options dialog is only visible for Visual Basic environment setups.
All macro commands consist of the prefix Macros followed by the project, module, and macro names, so to easily find them you can filter the list with the term Macros. Note that if you change a macro’s name, then any keyboard shortcut you assign to it will remain; and if you delete the macro entirely, Visual Studio will clean up keyboard shortcut mappings for you.
Creating Macros
Macros can be created in two main ways: by recording a series of actions you perform to a temporary macro and then saving it to convert it to permanent status, or by creating a macro from scratch in the Visual Studio Macros IDE.
347

Chapter 26
Recording Temporary Macros
Recording a macro is the quickest way to create a simple macro, but it cannot be used to create complex macros that use referenced namespaces and programming logic blocks to dictate what actions should be performed. Instead, recording simply records a series of commands as you perform them within the IDE, storing them in a straight sequential manner.
To begin recording a macro, use the Tools Macros Record Temporary Macro menu command or use the keyboard shortcut Ctrl+Shift+R. An extra toolbar will be displayed containing the three macro recording functions you have available (shown in Figure 26-5). This toolbar is only visible while you’re recording the temporary macro; it will not appear in the regular toolbar.
Pause Recording
Cancel Recording
Stop Recording
Figure 26-5
The additional macro commands available to you while recording are to pause the recording, to stop the recording, and to cancel it or save the command list to the temporary macro function. When you stop the recording, the macro will be added to a module called RecordingModule in whichever macro project is set to store the temporary macro.
To change the macro project to which temporary macros will be stored, right-click on the required macro project in the Solution Explorer and choose the Set as Recording Project menu command from the context menu.
Because a recorded macro is considered temporary, if you record a second macro before saving the first one, the first macro will be overwritten — only one temporary macro entry is possible at a time. Therefore, to save the sequence of commands you performed in a recording session, use the Tools Macros Save Temporary Macro menu command. Using this command will prompt you to set a new macro name.
Recording Issues
When recording a macro, the Visual Studio IDE keeps track of any text you change and any menu items or keyboard shortcuts that invoke standard Visual Studio commands. However, you can perform a number of actions within the IDE that are not included in the recording session. Two major features not included are any actions you perform with the mouse and any user interface changes you make.
These unrecorded user interface changes include adding or moving controls on a Windows form, setting properties on controls, navigating the contents of tool windows, and opening or closing windows. In
348

Macros
addition, mouse input is generally not recorded unless it is used to activate different windows in the environment. In some systems (it depends on your mouse driver), you won’t even be able to use your mouse to change the insert marker or select blocks of text.
If you perform any of these functions while recording, they simply will be ignored, and your resulting macro will only have the commands on either side of the omitted function, which could cause unexpected problems.
Remember that recording will save everything you do, including typing errors and cursor movements. Therefore, if you are creating a macro that is designed to work on a single code statement, make sure you position the cursor where you want the macro to start before recording, rather than position it after the recording has commenced.
With these issues in mind, using the Record Macro feature can give you a good head start in creating your macro; a combination of recording and manual editing of the macro code usually results in the most efficient way of creating what you need.
The Visual Studio Macros Editor
The other way to create a macro is to use the Visual Studio Macros editor directly, or to first create the macro stub in the Macro Explorer and then switch to the Visual Studio Macros editor to create the commands to perform. The advantage of using the Visual Studio Macros editor is that you have full control over the macro code, and can include functionality that cannot be recorded, such as conditional code and loops.
You can access the Visual Studio Macros IDE through the Tools Macros submenu or by right-clicking the macro you want to edit in the Macro Explorer and selecting the Edit command. Either way, the Visual Studio Macros environment will be loaded and displayed with the current macro active (see Figure 26-6).
Although macros have their own standalone development environment, it shares many features with its bigger cousin, Visual Studio 2005. Many of the menus and toolbars are replicated, and the macro code is automatically outlined, formatted, and syntax colored in the same way as Visual Basic code is in the main IDE.
The Macros IDE also has a subset of the tool windows available in Visual Studio 2005, including a Project Explorer that loosely combines the Macro Explorer and Solution Explorer, along with Toolbox and Properties tool windows. Like the Visual Studio IDE, these windows can be docked, pinned, moved, and resized in whatever configuration you want. The IDE in Figure 26-6 shows the default configuration, with the Project Explorer docked to the left side of the main workspace area and the Toolbox and Properties windows pinned to the same side but hidden.
The Macros IDE also shares the IntelliSense engine, enabling you to find members of objects through the Member List as well as providing feedback about parameters in function calls. With the same features present in Visual Studio 2005, you can use the descriptions in the appropriate chapters to customize the appearance and performance of the Macros IDE with the Options pages, including project locations and text editor settings, as discussed in Chapter 2, as well as customize toolbars and menus, covered in Chapter 5.
349

Chapter 26
Figure 26-6
The Project Explorer gives you the same kind of options as the Solution Explorer, including the ability to create new items such as classes and modules. Macro projects have their own set of item templates that you can use to create new items. In a default installation, using the Add New Item command will give you access to new modules, classes, and blank code modules (see Figure 26-7).
Figure 26-7
350

Macros
Generally, macros are stored in standard modules instead of class definitions because they are executed directly, so the main purpose for classes in your macro projects is when you require them internally.
The DTE Object
Every standard macro module includes several Imports statements to bring in line the namespaces normally used in macro code. Besides the familiar System and System.Diagnostics namespaces, the other two mandatory namespaces to be included are the EnvDTE and EnvDTE80 namespaces shared by the Visual Studio add-in extensibility model discussed in Chapter 32.
Along with these namespaces are some implicitly defined objects that you can use to access the components of Visual Studio. Primary in this set is the DTE object, which represents the top-level object in the Visual Studio 2005 automation model. The DTE object actually implements the EnvDTE80.DTE2 interface as well as the EnvDTE interface, and provides access to the following useful members in your code:
Member |
Description |
|
|
ActiveDocument |
Returns the currently active document in the main workspace of |
|
Visual Studio 2005. You’ll generally need this object to manipulate |
|
code directly. |
ActiveWindow |
Contains the currently active window, which is not necessarily the |
|
currently active document |
CommandBars |
Returns a collection of CommandBar objects equivalent to the Com- |
|
mandBars collection in Visual Studio 2005 |
CommandLineArguments |
Contains a string with the command-line arguments of the current |
|
execution of the Visual Studio 2005 environment |
DisplayMode |
Returns the current display mode, which can be either MDI or Tabbed |
|
Documents. You can also use this member to change the display |
|
mode programmatically in the macro. |
Documents |
Returns a collection of all open documents in the IDE. Note that this |
|
isn’t all documents in the currently loaded solution. |
LocaleID |
Allows you to interrogate the locale under which the IDE is running |
|
and adjust your code accordingly |
MainWindow |
Returns a Window object that represents the main IDE window |
Mode |
Determines whether the IDE is in design or debug mode |
Properties |
Contains all available properties in the Options dialog of Visual Stu- |
|
dio 2005. It does this by storing the individual properties as items in |
|
a two-dimensional collection that is keyed by category and individual |
|
Options pages. |
Solution |
Contains the Solution object for the currently open solution and |
|
returns all associated projects in that solution |
|
|
|
Table continued on following page |
351

Chapter 26
Member |
Description |
|
|
StatusBar |
Provides access to the main status bar of the Visual Studio IDE, |
|
enabling you to provide information as your macro executes |
ToolWindows |
Enables you to quickly find the main tool windows. You can also use |
|
the more generic Windows collection to get to the tool windows by |
|
name. Tool windows accessible in this collection include Command, |
|
Error List, Solution Explorer, Task List, and Toolbox. |
Windows |
A complete collection of all windows that belong to the Visual Studio |
|
IDE. Each window is referenced through the Item property of the |
|
Windows collection, rather than being explicitly named as they are in |
|
the ToolWindows collection, but this means you can reference any |
|
window currently available in the IDE. |
|
|
In addition to these members, several other members exposed by the interface can be quite useful in your macro code. The GetObject method enables you to late bind to any object that the extensibility model can interface with at runtime.
ExecuteCommand will run any Visual Studio 2005 command with the following syntax:
DTE.ExecuteCommand(commandName, commandArgs)
The commandName argument should be a string containing a single command that you could enter in the Command window — for example, File.NewFile or Tools.Options.commandArgs are used to pass over any parameters that the command might require.
The ItemOperations object provides shortcuts to common file-related actions such as NewFile or AddNewItem. The following two statements are equivalent:
DTE.ExecuteCommand(“File.FileNew”)
DTE.ItemOperations.NewFile
Typically, the members of the ItemOperations object accept parameters to customize their behavior. For example, to create a plain text file with the name myFile.txt, you could amend the previous statement as follows:
DTE.ItemOperations.NewFile(“General\Text File”, “myFile.txt”)
Your macro code can also be used to intercept most of the Visual Studio IDE events as they occur. Every macro project includes an additional module named EnvironmentEvents. Within this module is a section that defines most of the event objects you can use in your macros, in the following form:
<System.ContextStaticAttribute()> _
Public WithEvents DTEEvents As EnvDTE.DTEEvents
If the event you want to trap is not included in the event objects automatically inserted — for example, if the event were in the CommandEvents object — you can add it using the same syntax as the existing events, remembering to prefix the event declaration with the System.ContextStaticAttribute attribute. You can also use this method to define the IDE event objects in other modules in your code.
352

Macros
Once the appropriate events object is added to the module, you can define event handler routines for the events in the same way as you would in a normal Visual Basic project. First, select the appropriate event object from the Class list, and then the event you want to handle from the Method Name list. The Macros IDE will automatically generate the event handler. For example, choosing first the TaskListEvents object from the Class list, and then the TaskAdded event from the Method Name list will generate the following code:
Private Sub TaskListEvents_TaskAdded(ByVal TaskItem As EnvDTE.TaskItem) _
Handles TaskListEvents.TaskAdded
End Sub
Sample Macros
As mentioned previously, Visual Studio 2005 ships with a collection of sample macros. You can use these macros as a basis for your own functionality and to review common programming tasks. If you’re serious about building macros, it’s worth your while to take a look through the samples; there is a good chance that the very solution you’re trying to implement is already present in one form or another.
The following sample macros come from the Accessibility group and are used in Chapter 40 in the discussion about how to tweak your environment through the use of keyboard shortcuts. Each of the macros discussed in that section uses the Visual Studio IDE’s Properties object to customize the FontSize setting for the Text Editor (the main code editor). The easiest to follow is IncreaseTextEditorFontSize():
‘ Increases the font size used within the editor. Public Sub IncreaseTextEditorFontSize()
Dim textEditorFontsAndColors As Properties
textEditorFontsAndColors = DTE.Properties(“FontsAndColors”, “TextEditor”) textEditorFontsAndColors.Item(“FontSize”).Value += fontSizeIncrement
End Sub
As mentioned in the previous discussion about the DTE object, the Properties collection provides direct access to every property setting available from the Options dialog of Visual Studio 2005. In this case, the code accesses the TextEditor settings found within the Fonts and Colors page in the Options dialog, increasing the FontSize setting by a preset constant (defined elsewhere in the macro code module).
The functionality of this macro could have easily been achieved with a single line instead of expanding it out into multiple statements, but this way you can more easily customize it with additional code if needed. If you do prefer brevity, the shortened version of the function looks like this:
Public Sub IncreaseTextEditorFontSize()
DTE.Properties(“FontsAndColors”, “TextEditor”).Item(“FontSize”).Value += _
fontSizeIncrement
End Sub
The DecreaseTextEditorFontSize macro extends the functionality of the Increase macro by adding a condition to the logic. This is to avoid situations where the macro tries to set the font size too small. The full macro appears in the following listing:
‘ Decreases the font size used within the editor.
Public Sub DecreaseTextEditorFontSize()
353

Chapter 26
Dim textEditorFontsAndColors As Properties
Dim fontSize As [Property]
textEditorFontsAndColors = DTE.Properties(“FontsAndColors”, “TextEditor”) fontSize = textEditorFontsAndColors.Item(“FontSize”)
If fontSize.Value >= minimumSupportedEditorSize Then fontSize.Value -= fontSizeIncrement
End If End Sub
This code also illustrates another way of referring to individual properties. By using the Property object, you can directly assign a reference to a property to your own variables and then change the variable instead of having to fully specify the property each time.
The third sample macro resets the font size to match the system font. In addition to setting the FontSize property value in a similar way to the previous two macros, the UpdateTextEditorFontSizeTo MatchDisplayProperties macro also demonstrates how you can use the normal .NET Framework objects to gain information about the system and user. In this case, the code retrieves the setting for the size of the menu font used by the system:
‘ Changes the font size to match the font size of the operating system. Public Sub UpdateTextEditorFontSizeToMatchDisplayProperties()
Dim textEditorFontsAndColors As Properties Dim font As System.Drawing.Font
Dim pointSize As Integer Dim fontSize As [Property]
‘Get font size from menu font to use as an approximation. font = System.Windows.Forms.SystemInformation.MenuFont pointSize = font.GetHeight() - 3 ‘ Subtract 3 for adjustment.
‘Update the text edit font size.
textEditorFontsAndColors = DTE.Properties(“FontsAndColors”, “TextEditor”) fontSize = textEditorFontsAndColors.Item(“FontSize”)
fontSize.Value = pointSize End Sub
Building and Deploying
When you’re ready to build your macro project, you can customize the way the build process will work by accessing the Build Property Pages (see Figure 26-8). To access the Build options, right-click the project you want to customize in the Project Explorer and choose Properties.
The Build options for macros are a simplified version of the Visual Basic 2005 settings, with Option Strict, Option Explicit, and Option Compare represented, as well as a simple customization of how warnings are dealt with during the compilation of the macro code. In addition, by default the macro project will have the Generate Debugging Information option enabled, which will allow you to debug any macros that have runtime errors.
354

Macros
Figure 26-8
When debugging symbols are included, if the macro is executed in Visual Studio and an error occurs, then the code will switch over to the Macros IDE, where you can step through the code and examine the various objects using the fully featured debugging windows provided by Visual Studio 2005. Because macros are built on the Visual Basic engine, you can use the Edit-and-Continue feature of the language to quickly amend any problems encountered while you’re debugging the macro.
Summar y
The macros functionality in Visual Studio 2005 is a fully featured set of tools, including the capability to create temporary macros on-the-fly by recording keystrokes and certain actions in the IDE, as well as quickly load or remove entire macro projects that can contain dozens of macros grouped into logical categories. Supporting this, Visual Studio 2005 provides a number of interfaces to the macros feature, including a Macro Explorer window and a full Macros submenu accessible from the Tools menu.
The macros you create can be extensive, complete with program conditional and looping logic; have access to the majority of the IDE’s objects; and have the capability to intercept the events raised from Visual Studio 2005. However, while this will deal with most repetitive tasks in the IDE, in some cases it won’t suffice. Chapters 32 through 34 deal with extending Visual Studio 2005 further with third-party tools and add-ins that you can create yourself.
355