WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Developing Visual Studio Project Wizards
Pages: 1, 2, 3, 4, 5, 6

Signing the Wizard Assembly

A signed assembly is one that has been compiled with a public key, which provides it with a unique identify. All signed assemblies can be identified by strong name in addition to friendly name. (We'll see how to determine an assembly's strong name in the section, "Modifying the .vstemplate File."

Visual Studio 2005 makes the process of generating a signed assembly extremely easy. To sign an assembly, open the wizard project's Properties dialog and select the Signing tab, as shown in Figure 1. Check the "Sign the Assembly" box, and use the "Choose a strong name key file" combo box to either navigate to an existing key file, or have Visual Studio generate a new key file.


Figure 1. The Signing tab of the Project Properties dialog

Registering the Wizard Assembly in the GAC

Once you've compiled the assembly containing the wizard, you must register it in the GAC. To do this, you use gacutil.exe, the Global Assembly Cache utility. To do this, open a console window and navigate to the directory contains the wizard assembly. Next, assuming that the path to GACUTIL is in your PATH environment variable, type in the command:

GacUtil /i <wizard_assembly_name>.dll

where wizard_assembly_name is the root filename of your wizard assembly.

You can have Visual Studio take care of registering your assembly in the GAC as part of the build process. To this, you just have to provide the command line for a post-build event. Visual Studio executes it after it has attempted to build your project.

To have Visual Studio automatically register your wizard assembly after a successful build:

  1. Open the wizard project's Properties dialog, and select the Compile tab.
  2. Click the Build Events button at the bottom of the tab page.
  3. Make sure that On successful build is selected in the Run the post-build event drop-down list box.
  4. In the Post-build event command line text box, enter code like the following:
  5. gacutil /u <assembly_name>
    gacutil /I <assembly_name>.dll
    where <assembly_name> is the root name of the wizard assembly.

If the path to GACUTIL is not in the PATH environment variable, you'll have to add a fully qualified path. Also, the script works on the current directory, which is the directory in which the compiled assembly is stored. If you want to copy the assembly to some other location, you should change to that directory before registering the new version of the assembly in the GAC.

Note that this script unregisters the existing version of the assembly before registering the one just compiled. You should always unregister the existing version of the assembly before registering the new version. This prevents the .NET runtime from working with a cached version of your assembly that doesn't necessarily reflect the latest changes. (Needless to say, forgetting to do this makes debugging an interesting experience.)

Modifying the .vstemplate File

Now that your assembly is signed and registered, you just have to link it to the template whose selection activates it. To do this, you modify the .vstemplate file that Visual Studio creates when you export a template.

When Visual Studio exports a template file, it creates a ZIP file that contains all of the template's files. The format of this ZIP file, however, is different than the standard ZIP file format, which means that, while you can view and extract the files in the Visual Studio-generated ZIP file, you can't replace them. In other words, to integrate a wizard with a template, you'll have to extract the files from the existing template file, modify the .vstemplate file, and save the files to a new ZIP file.

The modification required to the .vstemplate file is itself quite simple. The .vstemplate file is an XML file. At the end of the template file, but before the closing </VSTemplate> tag, add a <WizardExtension> section. The <WizardExtension> section contains two tags that define the wizard. The first, the <Assembly> tag, provides the strong name of the wizard assembly. The second, the <FullClassName> tag, provides the fully qualified type name of the wizard class (that is, of the class that implements IWizard). You can get the strong name of a wizard assembly by opening a console window and (again assuming that the path to GACUTIL is in your PATH environment variable) entering the following command:

GacUtil /l <wizard_assembly_name>

where wizard_assembly_name is the name of the assembly, without its .dll extension. In Figure 2, for example, GacUtil is used to display the strong name of an assembly named WizardVB1.


Figure 2. Getting the strong name of an assembly

The finished definition of a wizard in a .vstemplate file might look something like the following:

...
   </TemplateContent>
   <WizardExtension>
      <Assembly>wizardvb1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2e58463dcf7e9cb7</Assembly>
      <FullClassName>CustomWizards.Wizard1</FullClassName>
   </WizardExtension>
</VSTemplate>

A Simple Example

Let's look at a very simple example that suggests some of the potential of templates. We have an class library for application development that has two versions in two different assemblies, AppLib and AppLib2. Each version supports a different kind of application. Version 1 is for building console applications. The classes in Version 2, which derive from and call methods in the Version 1 library, support Windows applications. We want a project type that allows developers to specify which version of the class library they wish to use, and that handles adding the necessary references and making the initial call to a library method.

The Class Libraries

To illustrate, we can create a very simple assembly that displays a message to the console. Its Visual Basic source code is:

Namespace MyCompanyApp
   Public Class AppLib
      Public Shared Sub DisplayGreeting()
         Console.WriteLine(GetMessage())
      End Sub

      Public Shared Function GetMessage() As String
         Return "Welcome!"
      End Function
   End Class
End Namespace
The version 2 library, written in C#, is even simpler:
using MyCompanyApp;
using System;
using System.Windows.Forms;

namespace MyCompanyApp
{
   public class AppLib2 : AppLib
   {
      public static void DisplayGreetingDialog()
      {
         MessageBox.Show(GetMessage());
      }
   } 
}

Both assemblies should be compiled and placed in the GAC.

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow