9.1 Wizard Basics

Wizard is the generic name for the VS.NET facilities for creating new projects or items. Each of the project types listed in the New Project (Ctrl-Shift-N) and Add Project dialogs is a wizard, as are each of the items in the Add New Item dialog (Ctrl-Shift-A). Some wizards do nothing more complex than creating a new file, but the more advanced ones create several files and may even present a user interface to allow the user to configure the way in which the files are created. However, all wizards are based on the same underlying mechanisms.

Two main types of wizards are available in all languages: project wizards and item wizards. (C# and VC++ support a third wizard type: context wizards. However, unlike project and item wizards, you cannot write your own custom context wizard without writing a package, as only packages allow you to extend VS.NET context menus. See the next chapter for information on writing packages.) Each type of wizard uses the same underlying infrastructure, but each serves different purposes.

Project wizards

VS.NET runs a project wizard when you select a project template from the New Project or Add Project dialog box. The wizard may present a UI to let you tailor the new project. The wizard then runs and copies a set of template files and adds them to your project. When the wizard runs, it may dynamically alter the name and contents of these files based upon the name you gave the project and the input you provided to the UI. The wizard may choose to add certain files only if particular input conditions are met.

Some wizards, such as the ATL Project Wizard, display a user interface. Some, such as the C# Windows Application Wizard, do not.

Item wizards

An item wizard runs when you add a new item to your project. Some item wizards will display a UI, although this is less common than with project wizards.

Context wizards

C# and VC++ provide context wizards, which allow you to add files or to add text to an existing file. Context wizards are executed from the Class View window. For example, if you right-click on a C# or C++ class in the Class Viewer, the context menu will have an Add item, allowing you to add new class members.

9.1.1 Implementation Choices

VS.NET supports three main wizard implementation styles. You can write a one-file item wizard with no code, you can use the VS.NET wizard engine, or you can write your own custom wizard engine.

The simplest style is the one-file wizard, but this is the least flexible. You will not be able to display a user interface nor will you be able to customize the file.

The most popular approach is to use the VS.NET wizard engine. The majority of the built-in wizards use this technique. The wizard engine allows you to build a user interface for your wizard in HTML and to control its operation with script files. It also supplies a mechanism that lets your wizard modify parts of the files that it adds to the project. For example, if your wizard adds a class definition to a project, you can write a template file that contains the class definition but allows features such as the class name to be set dynamically.

Instead of using the built-in wizard engine, you can also write your own custom engine. This lets you use any language capable of implementing a COM component, rather than being limited to scripting languages. It also lets you use any UI technology, rather than having to use HTML. However, it does require more effort to implement than the other two techniques, since very little is automated for you.

Regardless of which of these implementation styles you use, the way in which you add new wizards to VS.NET is the same.

9.1.2 Adding Wizards

In order for a wizard to be available to the user, you must copy certain files into the correct directories. VS.NET also needs to know which language your wizard supportsfor project wizards, this indicates the project type under which your wizard should appear in the New Project and Add Project dialogs. For item wizards, VS.NET must know which language the wizard supports in order to know when to make the wizard availablewhen the Add New Item dialog is displayed, it should contain only items appropriate to the current project's language. (This dialog must not offer to add C#-based items to a VB.NET project, for example.)

Each language uses a different set of directories for wizards and their configuration files. The VS.NET install directory (typically C:\Program Files\Microsoft Visual Studio .NET 2003) has four subfolders: VC#, VB7, VC7, and VJ#, and each of these in turn has subdirectories that contain the wizard files and wizard configuration information.

To indicate to VS.NET what kind of wizard yours is, and the language it is designed for, you copy one or more files into an appropriate directory. Table 9-1 shows which directories you should use for each language, according to whether you are creating a project wizard or an item wizard.

Table 9-1. Wizard type locations
 

Project wizard

Item wizard

C#

VC#\CSharpProjects

VC#\CSharpProjectItems

VB

VB7\VBProjects

VB7\VBProjectItems

C++

VC7\vcprojects

VC7\vcprojectitems

J#

VJ#\VJSharpProjects

VJ#\VJSharpProjectItems

Each of the directories listed in Table 9-1 contains one or more .vsdir files. The .vsdir files contain lists of wizards. For example, the .vsdir files in the VC#\CSharpProjects folder contain entries for all of the items listed in the Visual C# Projects section of the New Projects dialog. If you are using the Professional edition (or better) of VS.NET, this particular directory will contain three .vsdir filesCSharp.vsdir, CSharpEx.vsdir, and DevApp.vsdir, which contain the basic, advanced, and Smart Device project types, respectively. There can be any number of .vsdir files in a particular directoryVS.NET will just concatenate them. To add new wizards, you can therefore simply add your own .vsdir filesthere is no need to modify the existing ones.

For each wizard there must be a corresponding line in a .vsdir file. These entries consist of a series of fields separated by a | character, and they look like this:

Path|PackageID|Name|Order|Description|IconPath|IconID|Flags|BaseName

The first field, Path, is usually the relative path to the wizard's .vsz file, which contains the information needed to run the wizard (more on this in a minute). However, for item wizards, you can instead just specify the relative path of any fileif the specified file does not have the .vsz extension, VS.NET will automatically copy that file into the project when the item is selected. This is useful for simple item templates in which the contents of the new item are always the same. (This is how you implement the one-file wizards mentioned earlier.)

The second item in a .vsdir entry, PackageID, can be either 0 or the GUID of a VS.NET package. (See Chapter 10 for more information on VS.NET packages.) When a GUID is supplied, it is used for localizationthe wizard's name and description can be stored as resources in the package. In this case, the third and fifth items in the .vsdir entry (Name and Description) are resource IDs. The Name will be displayed in the template list on the right of the relevant New/Add dialog, underneath the icon for the template. The Description will appear in the middle of the dialog when the template is selected. When these fields contain resource IDs, VS.NET will display appropriately localized strings in the dialog. Example 9-1 shows an entry that uses this techniquethis is the entry for the C# Class Library project. (.vsdir entries are quite long, so this one has been split across multiple lines to make it fit. In the .vsdir file itself, each entry is on its own line.)

Example 9-1. .vsdir entry with package ID
CSharpDLL.vsz|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|

#2322|20|#2323|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|4547| |ClassLibrary

Localization of the name and description requires a package ID, so unless you are a Visual Studio Integration Partner (VSIPsee Chapter 10) and are writing your own package, you will not be able to use this feature for your own wizards. If you are not writing a package, you can just put strings in the Name and Description fields, specifying 0 for the package ID, as Example 9-2 shows.

Example 9-2. .vsdir entry with raw strings
MyWizard.vsz|0|My Project|0|My customized project|0|0|0|MyProject

The fourth field, Order, determines this item's position in the list in the relevant dialog. The lower the number, the earlier it will appear. Example 9-2 has specified an Order of 0. Since none of the built-in wizards have an Order lower than 1, this guarantees that the new wizard will appear first.

The sixth and seventh items, IconPath and IconID, indicate the icon to be used for this wizard in the New Project and Add New Item dialogs. The IconPath can be either another package ID or a string containing the relative path to the DLL. The IconID is the resource id of the icon in the DLL specified by IconPath.

You are not required to supply an icon. In Example 9-2, both IconPath and IconID are 0, which causes VS.NET to use a default icon.

The eighth field, Flags, controls certain features of the New/Add Project/Item dialogs when the template is selected. The supported flag values are:

VSDIRFLAG_NonLocalTemplate (1)

Used only in project wizards. This flag is set for all web projectsit will cause the New/Add Project dialog's Location field to require a URL rather than a filesystem path. All the project files for such a template will be stored on a web server rather than on the filesystem. See Chapter 4 for more information about web projects.

VSDIRFLAG_BlankSolution (2)

Used only in project wizards. Indicates that VS.NET should just create a blank (empty) solution and not a new project. This flag is used to support the Blank Solution project type in the Visual Studio solutions category, and you would not normally use this in your own templates.

VSDIRFLAG_DisableBrowseButton (4)

Used only in project wizards. Disables the Browse button for this project/item.

VSDIRFLAG_DontAddDefExtension (8)

Used only in item wizards. Prevents a default extension from being appended to the name provided for the item.

VSDIRFLAG_DisableLocationField (32)

Disables the location field for this project or item.

VSDIRFLAG_DontInitNameField (4096)

Prevents VS.NET from initializing the Name field for the project or item with a valid default name.

VSDIRFLAG_DisableNameField (8192)

Disables the Name field for the project or item.

The flag names in this list are those given in the documentation. However, you cannot use these names in the .vsdir filesyou must always use raw numbers. So, if your wizard is for a web project, you would specify the value 1, and not the string VSDIRFLAG_NonLocalTemplate.

The last item in the .vsdir entry, BaseName, is used by VS.NET to provide a default suggested name for the new item or project. As with all the other text fields, this can be either a resource ID or a string. (Again, to use a resource ID, you must supply a package ID, so only those signed up for VSIP will be able to use this. The rest of us must supply a raw text string, as Example 9-2 does.)

9.1.2.1 Item wizard .vsdir files

Item wizards are a little more complex than project wizards, because they are subdivided into multiple categories. If you look at the .vsdir file in one of the project item directories listed in Table 9-1, such as CSharpItems.vsdir in the VC#\CSharpProjectItems directory (shown in Example 9-3), you will see that it doesn't actually hold references to wizards. It contains just two lines, both of which are references to folders: WebProjectItems and LocalProjectItems. This is because the set of project items available in the Add New Item dialog is different for local projects and web projects. Moreover, these two folders are divided into more folders, which correspond to the structure that the Add New Item dialog presents in its Categories tree on the left. This means that if you look in the .vsdir files in the WebProjectItems or LocalProjectItems, you will see that these too contain references to other directories.

Example 9-3. CSharpItems.vsdir
LocalProjectItems|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|#2339|10

WebProjectItems|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|#2340|20

In order for an item wizard to show in the appropriate folders in the Add New Item dialog, you will add .vsdir files in at least two places. Even if you want the item to appear only in local projects, you will still need to add a .vsdir entry in the LocalProjectItems subdirectory and the relevant subcategory (e.g., the Utility directory). If you add it to just the subcategory directory but not the LocalProjectItems subdirectory, your item will not appear when the user selects the top-level Local Project Items category. (All of the VS.NET item templates appear twiceonce in the top-level category and once in the more specific category.)

Although you need to create or modify .vsdir files in at least two directories, everything else remains the same as it was for a project wizard.

Most of the information in the .vsdir file is concerned with how the template will be presented in the New/Add Project or Add Item dialog. However, when the user elects to run the wizard by clicking OK in the relevant dialog, VS.NET will refer to the first field in the .vsdir entry, Path. As already mentioned, for simple item wizards, this can be just the path of a source file that will get copied and added to the project. However, for project wizards or more sophisticated item wizards, Path will refer to a .vsz file that tells VS.NET what to do next.

9.1.3 .vsz Files

When the user creates a new project or adds a new item to a project, VS.NET loads the .vsz file for the corresponding wizard, as specified in a .vsdir file. The .vsz file it uses is determined by the first field in the wizard's .vsdir file entry. Example 9-1 specifies the CSharpDLL.vsz file, which is shown in Example 9-4.

Example 9-4. The C# class library .vsz file
VSWIZARD 7.0

Wizard=VsWizard.VsWizardEngine.7.1

Param="WIZARD_NAME = CSharpDLLWiz"

Param="WIZARD_UI = FALSE"

Param="PROJECT_TYPE = CSPROJ"

The first line of the .vsz file indicates what version of VS.NET this .vsz file is designed for. (VS.NET 2003 will accept Versions 6.0, 7.0, and 7.1. Although 7.1 is technically the version number for VS.NET 2003, in practice, all of the built-in templates specify 7.0, as this example does.)

The second line is the ProgID of the COM coclass that VS.NET will create in order to execute this wizard. Most wizards just specify the wizard engine that ships with VS.NETVsWizard.VsWizardEngine.7.1. (In VS.NET 2002, the built-in wizards all specified just VsWizard.VsWizardEngine.) The wizard engine is described in the next section.

You are not required to use the built-in wizard engine. You may instead supply your own class, which must implement the IDTWizard interface. See Section 9.3 for more information.

The remainder of the file is used to supply parameters to the wizard class. If a custom wizard class were in use, you could pass whatever parameters you like here. However, since Example 9-4 is using the wizard engine, all of the parameters that it passes are standard wizard engine parameters.