Over the years, I’ve built more than a few project templates with wizard support. Usually for experimental purposes to help answer customer inquiries concerning templates and wizards. Lately, I’ve found myself regularly following steps similar to what I outlined in my previous blog entry:
When you find yourself doing something often enough, you just may find yourself motivated enough to automate things a bit. So without further ado, I’d like to present: The VSX Template Wizard.
Currently, this particular VSIX package doesn’t reside in the Visual Studio Extension Gallery, due to a limitation which prevents us from uploading .VSIX files with multiple .zip files to the gallery. This is a gallery limitation that the Visual Studio team is hoping to address in the not to distant future. Until then, the .VSIX will simply reside here, with the source published as a sample at: Custom Templates and Wizard to create VSIX Deployable Template with Wizard package
When installed, you will find a couple of new project templates, installed under the C#\Extensibility node of your New Project dialog. these new templates will allow you to easily create a VSIX Deployable Project (or Item) Template, with a custom IWizard implementation. The results of which, bear a striking resemblance to the afore mentioned walkthrough.
This VSIX was built with and targets VS 2013. I’ve published the source, to serve primarily as a sample. But in the event someone wants to build a similar VSIX for earlier versions of VS, the sample source may also serve as a template for that effort. The projects that these particular templates create, leverage the VSSDK, so that also needs to be installed.
Finally, you need to install the VSX Template Wizard.
Using the Template
1. Open the New Project Dialog, then find and select one of the new templates
2. Then click the OK button to create the Project (or Item) Template with Wizard project.
3. Examine/explore the resulting solution. You’ll find two projects in the solution similar to the following
Note, the first project is the template project responsible for creating the .zip file that contains the actual template that will be deployed when you install the resulting .VSIX. The second project (MyProjectTemplateWizard) creates the wizard assembly and packages it (and the .zip file from the first project) into a .VSIX that you can use to deploy your template and wizard to other machines.
The TemplateWizard.cs contains a rudimentary IWizard implementation, which you can customize to fit your specific needs. Some wizards require a UI, and others don’t. So you’ll want to customize the wizard functionality to fit your specific needs.
The Implementation Details:
Creating a project template that creates another project template, can be hard to get your head around. The VSXTempateWizard solution includes the following 4 projects:
- VSXItemTemplate – this project creates the VSXItemTemplate.zip, which creates a simple C# Item Template project.
- VSXProjectTemplate – this project creates the VSXProjectTemplate.zip, which creates a simple C# Project Template project.
- VSXWizardTemplate – this project creates the VSXWizardTemplate.zip, which creates the wizard assembly and VSIX Package.
- VSXTemplateWizard – this is the IWizard used by the VSXItemTemplate, VSXProjectTemplate and VSXWizardTemplate to glue everything together.
A Multi-Project Template that isn’t
The first thing you may notice, is that none of these templates are actually multi-project templates. Yet, when you create a new “Item Template with Wizard” project, or “Project Template with Wizard” project, you get a solution containing 2 projects as shown above. Hence, what we have here is a Multi-Project Template that isn’t a multi-project template.
One of the more frustrating limitations of the Multi-Project Template, is that you have almost no control over where its various projects are created, or how they get named. However, it’s entirely possible to seize control of this, if you designate one project to be the “primary” project, and implement an IWizard to add the additional projects after the first is generated. This is exactly what the VSXTemplateWizard does. The “trick” is to mark the subordinate projects as hidden (so they don’t show up in the New Project or New Item dialog). Then call Solution2.AddFromTemplate after the “primary” project has been completely generated (from the IWizard.ProjectFinishedGenerating method). See the VSXTemplateWizard.ProjectFinishedGenerating method in the VSXTemplateWizard.cs in the accompanying sample, for an example of this.
While examining the ProjectFinishedGenerating method also note of the usage of the VSLangProj.VSProject and EnvDTE.Configuration interfaces to change up the debugger settings for the wizard project. The resulting template and wizard projects are configured to run in the Experimental Instance of the IDE, so as to avoid mucking up your actual production environment.
I’ll be the first to admit the VSXTemplateWizard is a bit convoluted, but it’s used by all 3 of the templates, and I shamefully use a few static variables to store key info, to be used when the wizard is invoked a 2nd time when adding the VSXWizardTemplate project. Hence the checks for which .vstemplate invoked the wizard in the RunStarted method, and the conditional setting of various flags and replacement tokens.
There can be only one vstemplate
The VSXItemTemplate and VSXProjectTemplate both produce a “Project Template project”. This particular project type supports the presence of a single .vstemplate. Note that the “other” .vstemplate is actually named with a ._vstemplate extension. This is to ensure the project build properly, and that the ._vstemplate doesn’t accidentally get displayed in the New Project or Add Item dialogs. The ._vstemplate actually gets renamed to .vstemplate by using the TargetFileName attribute, in the owning .vstemplate. See the VSXItemTemplate.vstemplate or VSXProjectTemplate.vstemplate, as an example.
Generating the Key.snk file programmatically
A custom IWizard assembly needs to be built with a strong name. Given it’s not a good idea to distribute the same pre-generated key.snk file, the VSXTemplateWizard generates a new one for each VSXWizardTemplate. The APIs (like StrongNameGen) commonly used to generate the contents of a key.snk file are now deprecated. So the VSXTemplateWizard uses the new ICLRStrongName interface. This interface currently isn’t defined in managed code, so I “borrowed” the definition the CLR Runtime Team published on codeplex. See the VSXTemplateWizard.GenerateStrongNameKeyAndToken method in the VSXTemplateWizard.cs file, to see how this interface is retrieved and used to generate the content of the key.snk file.
I believe that pretty much covers it. Hopefully, you’ll find the VSX Template Wizard useful. It certainly saves me a bit of time setting up a new templates that need a custom wizard.