Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Visual Studio 2005 (2006) [eng]

.pdf
Скачиваний:
132
Добавлен:
16.08.2013
Размер:
21.9 Mб
Скачать

Chapter 25

folders, depending on whether they are a template for a single file or a full project. However, the one common element between all template folders is that they contain a .vstemplate file. This file is an XML document that determines what happens when the template is used:

<VSTemplate Version=”2.0.0” xmlns=”http://schemas.microsoft.com/developer/vstemplate/2005” Type=”Project”>

<TemplateData>

<Name>Application Template</Name>

<Description>Default Application template</Description> <ProjectType>VisualBasic</ProjectType> <SortOrder>1000</SortOrder> <CreateNewFolder>true</CreateNewFolder> <DefaultName>Application Template</DefaultName> <ProvideDefaultName>true</ProvideDefaultName> <LocationField>Enabled</LocationField> <EnableLocationBrowseButton>true</EnableLocationBrowseButton> <Icon>__TemplateIcon.ico</Icon>

</TemplateData>

<TemplateContent>

<Project TargetFileName=”StarterProject.vbproj” File=”StarterProject.vbproj” ReplaceParameters=”true”>

<ProjectItem ReplaceParameters=”true” TargetFileName=”AboutForm.vb”>AboutForm.vb</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”AboutForm.Designer.vb”>AboutForm.Designer.vb</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”AboutForm.resx”>AboutForm.resx</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”ApplicationEvents.vb”>ApplicationEvents.vb</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”MainForm.vb”>MainForm.vb</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”MainForm.Designer.vb”>MainForm.Designer.vb</ProjectItem>

<ProjectItem ReplaceParameters=”true” TargetFileName=”MainForm.resx”>MainForm.resx</ProjectItem>

<Folder Name=”My Project” TargetFolderName=”My Project”> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Application.myapp”>Application.myapp</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Application.Designer.vb”>Application.Designer.vb</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”AssemblyInfo.vb”>AssemblyInfo.vb</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Resources.resx”>Resources.resx</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Resources.Designer.vb”>Resources.Designer.vb</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Settings.settings”>Settings.settings</ProjectItem> <ProjectItem ReplaceParameters=”true”

TargetFileName=”Settings.Designer.vb”>Settings.Designer.vb</ProjectItem>

</Folder>

<ProjectItem ReplaceParameters=”true” TargetFileName=”SplashForm.vb”>SplashForm.vb</ProjectItem>

336

Code Generation Templates

<ProjectItem ReplaceParameters=”true” TargetFileName=”SplashForm.Designer.vb”>SplashForm.Designer.vb</ProjectItem>

</Project>

</TemplateContent>

</VSTemplate>

This sample illustrates the MyTemplate.vstemplate that was generated for the project template created earlier. At the top of the sample, the VSTemplate node contains a Type attribute that determines whether this is an Item template (“Item”), a Project template (“Project”), or a Multiple Project template (“ProjectGroup”). The remainder of the sample is divided into TemplateData and TemplateContent. The TemplateData block includes information about the template itself, such as the name, description, and icon that will be used to represent the template in the New Project dialog, whereas the Template Content block defines the structure of the template.

In the preceding example, the content starts with a Project node, which indicates the project file to use. The files contained in this template are listed using the ProjectItem nodes. Each node contains a Target FileName attribute that can be used to specify the name of the file as it will appear in the project created from this template. In the case of an Item template, the Project node is missing and ProjectItems are contained within the TemplateContent node.

For more information on the vstemplate file, the full schema is available at C:\Program Files\ Microsoft Visual Studio 8\Xml\Schemas\1033\vstemplate.xsd.

Extending Templates

Building templates based on existing items and projects limits what you can do because it assumes that every project or scenario will require exactly the same items. Instead of creating multiple templates for each different scenario (for example, one that has a main form with a black background and another that has a white background), with a bit of user interaction you can accommodate multiple scenarios from a single template. Therefore, this section takes the project template created earlier and tweaks it so users can specify the background color for the main form. In addition, you’ll build an installer for both the template and the wizard that you will create for the user interaction.

To add user interaction into a template, you need to implement the IWizard interface in a class library that is then strongly signed and placed in the GAC on the machine on which the template will be executed. Earlier releases of Visual Studio 2005 had the capability to use a nonsigned assembly placed within the template zip folder. However, despite being an incredibly useful way to deploy templates, this was deemed a security risk and removed. As such, to deploy a template that uses a wizard, you also need to deploy the wizard assembly to the GAC.

Template Project Setup

Before plunging in and implementing the IWizard interface, follow these steps to set up your solution so you have all the bits and pieces in the same location, which will make it easy to make changes, perform a build, and then run the installer:

337

Chapter 25

1.As you did earlier, start with the StarterProject solution on which you based the initial project template. Make sure that this solution builds and runs successfully before proceeding. Any issues with this solution will be harder to detect later, as the error messages that appear when a template is used are somewhat cryptic.

2.Into this solution add a Class Library project, in which you will place the IWizard implementation. You will also need to add a Setup project to the solution. To do this, select the Setup Wizard template and follow the prompts so that the Primary Output from the Class Library is included in the installer.

3.To access the IWizard interface, add references to the Class Library project to both EnvDTE.dll and Microsoft.VisualStudio.TemplateWizardInterface.dll, both located at

C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PublicAssemblies\. This should result in a solution that looks similar to what is shown in Figure 25-9.

Figure 25-9

As shown in Figure 25-9, both the primary output and content files from the Class Library project have been added to the installer. This action also adds a number of dependencies to the installer. Because the template will only be used on a machine with Visual Studio 2005, you don’t need any of these dependencies. Exclude them by clicking the Exclude menu item on the right-click context menu.

4.By default, when you add project outputs to the installer, they are added to the Application folder. In this case, add the primary output of the class library to the GAC, and place the content files for the class library into the user’s Visual Studio Templates folder. Before you can move these files, right-click the Installer project and select View File System from the context menu to open the File System view.

5.By default, the File System view contains the Application Folder (which can’t be deleted), the User’s Desktop, and the User’s Programs Menu. Remove the two User folders by selecting Delete from the right-click context menu.

338

Code Generation Templates

6.Add both the Global Assembly Cache (GAC) folder and the User’s Personal Data folder (My Documents) to the file system by right-clicking the File System on Target Machine node and selecting these folders from the list.

7.Into the User’s Personal Data folder, add a Visual Studio 2005 folder, followed by a Templates folder, followed by a ProjectTemplates folder. The result should look like what is shown in Figure 25-10.

Figure 25-10

8.To complete the installer, move the primary output from the Application folder into the Global Assembly Cache folder, and then move the content files from the Application folder to the ProjectTemplates folder (simply drag the files between folders in the File System view).

IWizard

Now that you’ve completed the installer, you can work back to the wizard class library. As shown in Figure 25-9, you have a form, ColorPickerForm, and a class, MyWizard. The former is a simple form that can be used to specify the color the background of the main form, as shown in Figure 25-11.

Figure 25-11

The event handler for the ellipses button opens the ColorDialog that is used to select a color, as shown in the following code snippet:

Public Class ColorPickerForm

Private Sub BtnPickColor_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles BtnPickColor.Click

Me.ColorDialog1.Color = Me.PnlColor.BackColor

If Me.ColorDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

339

Chapter 25

Me.PnlColor.BackColor = Me.ColorDialog1.Color

End If

End Sub

Public ReadOnly Property SelectedColor() As Drawing.Color

Get

Return Me.PnlColor.BackColor

End Get

End Property

End Class

The MyWizard class implements the IWizard interface, which provides a number of opportunities for user interaction throughout the template process. In this case, add code to the RunStarted method, which will be called just after the project creation process is started. This provides the perfect opportunity to select and apply a new background color for the main form:

Imports Microsoft.VisualStudio.TemplateWizard

Imports System.Collections.Generic

Imports System.Windows.Forms

Public Class MyWizard

Implements IWizard

Public Sub BeforeOpeningFile(ByVal projectItem As EnvDTE.ProjectItem) _ Implements IWizard.BeforeOpeningFile

End Sub

Public Sub ProjectFinishedGenerating(ByVal project As EnvDTE.Project) _ Implements IWizard.ProjectFinishedGenerating

End Sub

Public Sub ProjectItemFinishedGenerating _

(ByVal projectItem As EnvDTE.ProjectItem) _

Implements IWizard.ProjectItemFinishedGenerating

End Sub

Public Sub RunFinished() Implements IWizard.RunFinished

End Sub

Public Sub RunStarted(ByVal automationObject As Object, _ ByVal replacementsDictionary As _

Dictionary(Of String, String), _ ByVal runKind As WizardRunKind, _

ByVal customParams() As Object) _

Implements IWizard.RunStarted

Dim selector As New ColorPickerForm

If selector.ShowDialog = DialogResult.OK Then

Dim c As Drawing.Color = selector.SelectedColor

Dim colorString As String = “System.Drawing.Color.FromArgb(“ & _ c.R.ToString & “,” & _ c.G.ToString & “,” & _ c.B.ToString & “)”

340

Code Generation Templates

replacementsDictionary.Add _

(“Me.BackColor = System.Drawing.Color.Silver”, _ “Me.BackColor = “ & colorString)

End If End Sub

Public Function ShouldAddProjectItem(ByVal filePath As String) As Boolean _ Implements IWizard.ShouldAddProjectItem

Return True End Function

End Class

In the RunStarted method, you prompt the user to select a new color and then use that response to add a new entry into the replacements dictionary. In this case, you are replacing “Me.BackColor = System.Drawing.Color.Silver” with a concatenated string made up of the RGB values of the color specified by the user. The replacements dictionary is used when the files are created for the new project, as they will be searched for the replacement keys. Upon finding any instances of these keys, they will be replaced by the appropriate replacement value. In this case, you’re looking for the line specifying that the BackColor is Silver, replacing it with the new color supplied by the user.

The class library containing the implementation of the IWizard interface must a strongly named assembly capable of being placed into the GAC. To accomplish this, use the Signing tab of the project properties dialog to generate a new signing key, as shown in Figure 25-12.

Figure 25-12

After checking the Sign the Assembly checkbox, there will be no default value for the key file. To create a new key, select <New...> from the drop-down list. Alternatively, you can use an existing key file using the <Browse...> item in the drop-down list.

341

Chapter 25

Starter Template

You’re basing the template for this example on the StarterProject, and you need only make minor changes in order for the wizard you just built to work correctly. In the previous section you added an entry in the replacements dictionary, which searches for instances where the BackColor is set to Silver. If you want the MainForm to have the BackColor specified during the wizard, you need to ensure that the replacement value is found. To do this, simply set the BackColor property of the MainForm to Silver. This will add the line “Me.BackColor = System.Drawing.Color.Silver” to the MainForm.Designer.vb file so that it is found during the replacement phase.

Instead of exporting the StarterProject as a new template each time and manually adding a reference to the wizard, use a command-line zip utility (in this case, 7-zip, available at www.7-zip.org, was used, but any command-line zip utility will work) to build the template. This makes the process easier to automate from within Visual Studio 2005. If you zip the StarterProject folder, you would have all the content files for the template, but you would be missing the VSTemplate file and the associated icon file. This can easily be fixed by adding the VSTemplate file (created when you exported the project template) to the StarterProject folder. You can also add the icon file to this folder. Make sure that you do not include these files in the StarterProject itself; they should appear as excluded files, as shown in Figure 25-13.

Figure 25-13

To have the wizard triggered when creating a project from this template, add some additional lines to the VSTemplate file:

<VSTemplate Version=”2.0.0” xmlns=”http://schemas.microsoft.com/developer/vstemplate/2005” Type=”Project”>

<TemplateData>

...

</TemplateData>

<TemplateContent>

342

Code Generation Templates

...

</TemplateContent>

<WizardExtension>

<Assembly>WizardClassLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d2bbc1a3dd199c27, Custom=null</Assembly>

<FullClassName>WizardClassLibrary.MyWizard</FullClassName>

</WizardExtension>

</VSTemplate>

The <WizardExtension> node added in the following sample indicates the class name of the wizard and the strong named assembly in which it resides. You have already signed the wizard assembly, so all you need to do is determine the PublicKeyToken by opening the assembly using Lutz Roeder’s .NET Reflector (available at www.aisto.com/roeder/dotnet/). If you haven’t already built the WizardLibrary, you will have to build the project so you have an assembly to open with Reflector. Once you have opened the assembly in Reflector, you can see the PublicKeyToken of the assembly by selecting the assembly in the tree, as shown in Figure 25-14. The PublicKeyToken value in the VSTemplate file needs to be replaced with the actual value found using Reflector.

Figure 25-14

The last change you need to make to the StarterProject is to add a post-build event command that will zip this project into a Project template. In this case, the command to be executed is a call to the 7-zip executable, which will zip the entire contents of the StarterProject folder, recursively, into StarterTemplate

.zip, placed in the WizardClassLibrary folder. Note that you may need to supply the full path for your zip utility:

7z.exe a -tzip ..\..\..\WizardClassLibrary\StarterTemplate.zip ..\..\*.* -r

Referring to Figure 25-13, notice that the generated zip file (StarterTemplate.zip) is included in the Class Library project. The Build Action property for this item is set to Content. This aligns with the installer you set up earlier, which will place the Content files from the class library into the templates folder as part of the installation process.

343

Chapter 25

You have now completed the individual projects required to create the project template (StarterProject), added a user interface wizard (WizardClassLibrary), and built an installer to deploy your template. One last addition is to correct the solution dependency list to ensure that the StarterProject is rebuilt (and hence the template zip file recreated) prior to the installer being built. Because there is no direct dependency between the installer project and the StarterProject, you need to open the solution properties and indicate that there is a dependency, as illustrated in Figure 25-15.

Figure 25-15

Your solution is now complete and can be used to install the StarterTemplate and associated IWizard implementation. Once installed, you can create a new project from the StarterTemplate you have just created.

Summar y

This chapter provided an overview of how to create both Item and Project templates with Visual Studio 2005. Existing projects or items can be exported into templates that you can deploy to your colleagues. Alternatively, you can build a template manually and add a user interface using the IWizard interface. From what you learned in this chapter, you should be able to build a template solution that can create the template, build and integrate a wizard interface, and finally build an installer for your template.

344

Macros

Macros are a great way to automate simple tasks, and with Visual Studio 2005 you can easily create and maintain a full library of macros to perform all kinds of functions. Even better, the default installation comes with dozens of pre-built macros that you can immediately use in the Visual Studio IDE.

A macro is a set of commands grouped together into a batchlike, interpretative function. Instead of manually performing each of the commands in turn, you can run one macro function that will invoke the commands in sequence. Visual Studio 2005 macros are organized into complete Macro projects, which can contain multiple modules that in turn can contain multiple macros.

This organizational structure enables you to group macros into logical categories as well as divide your macro collection into manageable blocks. Keeping the macros organized into separate projects also enables you to share groups of macros with other developers more easily.

In this chapter you’ll take a look at the structure of a macro and learn how to create and use them effectively.

The Macro Explorer

To review the macros currently defined in an instance of Visual Studio, you can use the Macro Explorer tool window (see Figure 26-1). This window shares space with the Solution Explorer by default and can be accessed with the Tools Macros Macro Explorer menu command.

Each macros project loaded in Visual Studio 2005 is represented by a root node in the tree view, with the macros themselves divided into the modules that contain them. You can use the Macro Explorer to load or create additional macros projects by right-clicking the top level Macros node and choosing Load Macro Project or New Macro Project from the context menu.