Creating the .vsz File
As you saw in Chapter 6, to create an add-in you must provide information to Visual Studio .NET to let it know that the add-in is available to be loaded. This information, which is stored in the system registry, includes the programmatic identifier (ProgID) as well as information detailing how the add-in should be loaded. Likewise, a wizard needs a way to announce itself as being available; but unlike with an add-in, you must rely on the file system to make a wizard available. You do this by creating a hierarchy of folders in a specific location on disk and placing files with the extension .vsz in within this folder hierarchy.A .vsz file has a simple text-based file format. The file starts with the string "VSWIZARD 7.0", which tells Visual Studio .NET that the file declares a wizard and that the wizard should be run in Visual Studio .NET version 7 or later. The next line of text is a token that starts with "Wizard=" and is followed by the ProgID or the class identifier (ClassID) of the COM object implemented by the wizard. If we were to use the ProgID from the Wizard.cs code shown in Listing 7-1, the line in the .vsz file would appear as follows:
Wizard=MyWizard.Wizard
We could also use the ClassID format:
Wizard={E5D0A8B2-A449-4d3b-B47B-99494D23A58B}
After the line for the ProgID or ClassID, you can place a list of user-defined data. This data can be any string data that you want to pass to your wizard, and it can be static (hard-coded into the .vsz file during development) or generated when your wizard is installed by a setup program. Each line of this data starts with the token "Param=", and your wizard can require any number of these entries (including 0). Here's an example of this data:
Param=Hello World
Param=Second line of data
Each of these Param tokens is passed as an element of the CustomParams array when your wizard's Execute method is invoked and can be found within a wizard with code such as this C# snippet:
for(int i = 0 ; i < CustomParams.Length ; i++)
{
string data = (string)CustomParams[i];
System.Windows.Forms.MessageBox.Show(data);
}
When this code runs, the strings passed to CustomParams have the leading "Param=" stripped from each string; only the raw data is specified.NoteEven if you're using Visual Studio .NET 2003 (version 7.1), the first line of a .vsz file must start with the string 'VSWIZARD 7.0', not 'VSWIZARD 7.1'.
Where to Save .vsz Files
For a user to run your wizard, you must place the .vsz file in a specific location on disk so the New Project or Add New Item dialog box can find it and make that wizard available to be run. When the New Project or Add New Item dialog box is shown, a folder or number of folders on disk are read for the subfolders and files they contain. The names of these folders are inserted into the tree on the left side of the dialog box, and any subfolders are inserted as subitems of that tree node. As the user selects nodes in the tree, each file within the folder corresponding to the selected node is displayed in the list on the right side of the dialog box.For example, Figure 9-1 shows the New Project dialog box with the file system modified to add a folder called A Sub Folder under the Extensibility Projects folder, which is the folder on disk where the .vsz files are stored for the Add-in Wizard. When the contents of the Extensibility Projects folder are copied into the A Sub Folder folder, they appear on the right side of the dialog box if this new folder is selected. The A Sub Folder folder was created in the folder C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\Extensibility Projects (using the default installation location).
Figure 9-1. A new subfolder shown in the New Project dialog box

You can find the location to store your new project .vsz files programmatically using the TemplatePath property of the Solution object. The following macro displays message boxes showing the folder in which the .vsz files can be stored so that they will appear within the Visual Basic Projects and Visual C# Projects nodes on the right side of the New Project dialog box:
Sub VSZLocation()
'Display the .vsz path for Visual Basic Projects
MsgBox(DTE.Solution.TemplatePath( _
VSLangProj.PrjKind.prjKindVBProject))
'Display the .vsz path for C# Projects
MsgBox(DTE.Solution.TemplatePath( _
VSLangProj.PrjKind.prjKindCSharpProject))
End Sub
NoteThe TemplatePath property was poorly nameda better name would be VSZFilePath. Don't confuse the word Template in the property name with file templates (which we'll discuss later in this chapter).The constants prjKindVBProject and prjKindCSharpProject, which are defined in the metadata assembly VSLangProj.dll, are GUIDs in the form of a string. There are, as you probably know, project types other than those for Visual Basic and C#, but constants that can be passed to TemplatePath property for those projects types aren't found in any assembly. You can manually find the project type GUIDs for these other project types by poking around in the system registry. Under the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\Projects is a list of GUIDs; each GUID defines a project type that Visual Studio .NET supports. Replacing the argument to Solution.Template path with one of these GUIDs returns the path in which to store your .vsz file so that an entry for the wizard appears in the New Project dialog box for that project type. If we search through this area of the registry for vcproj (the extension used for Visual C++ project files), we'll find that the GUID for the Visual C++ project type is {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}. We can use this GUID to locate the path to where we can store .vsz files so they'll appear in the Visual C++ Projects node of the New Project dialog box:
Sub VSZLocation2()
'Display the .vsz path for Visual C++ Projects:
MsgBox(DTE.Solution.TemplatePath( _
"{07CD18B1-3BA1-11d2-890A-0060083196C6}"))
End Sub
As you can see in Figure 9-1, a different image is shown for each .vsz file found. You can associate an image with a .vsz file by placing an icon (.ico) file in the same folderone with the same name as the .vsz file but with the .ico extension. For the Add-in Wizard, the .vsz file on disk is called Visual Studio .NET Add-in.vsz. When the user selects the folder, a file called Visual Studio .NET Add-in.ico is searched for and, if found, used as the display image. If an icon for a .vsz file isn't found, the default icon for files as defined by Windows is used.The Add New Item dialog box uses the directory structure in a similar way to the New Project dialog box. You can add new folders, and any files with a .vsz extension that the user selects will be run as a wizard. The only difference between the Add New Item dialog box and the New Project dialog box is that the template directories are located in different places. Figure 9-2 shows the directory structure after it was modified for the Add New Item dialog box and a text file template was placed in that folder.
Figure 9-2. A custom folder in the Add New Item dialog box

You retrieve the location where the .vsz files are stored for this dialog box much like you retrieve the path for the New Project dialog box, but using a different method. Rather than using the Solution.TemplatePath method, you pass the project type GUID to the Solution.ProjectItemsTemplatePath method. You can use the following macro to find the path to where C# Add New Item .vsz files can be stored:
Sub ProjectItemVSZLocation()
'Display the .vsz path for C# project items:
MsgBox(DTE.Solution.ProjectItemsTemplatePath( _
VSLangProj.PrjKind.prjKindCSharpProject))
End Sub