Creating Project templates for Visual Studio ( VSIX / C# / 2019 )
A small exploration for creating waveform vizualization on the web, simple and raw
After starting another technology book or exploring a new framework or platform the thing that wastes a lot of time and its annoying is boilerplate and needless setups. Having a nice and fast start of a project helps you concentrate on the important part learning and working on your own code. Because some of the things i work with were C++ based Visual Studio is a great platform that offers plenty of extensibility options. The basic thing you can do to create a project template in VS is after making your project all set up use the Export Template feature.
This creates a new zip file that contains all VS needs to add the project template to your installation. The most important file that gets created is MyTemplate.vstemplate , it contains all the info about what files are included what string replacement should be made and how VS should setup projects created with this template. This action can be easily used to save you time in making more complex template. Creating a more complex project or even one that’s not derived from the basic project types or needs more complex generation of the data in the template we have to make a VSIX extension project.
Before we begin we need to install the Visual Studio SDK, this is easier to do compared to older versions because its part of the features installer. From Tools → Get Tools and Features
so we can create a VSIX project.
As a start we will need a VSIX project to pack things up neatly, it creates a single file thats easy to distribute and can even be added to the marketplace.
Create C# Project Template
This will be our placeholder project containing all our template files. To make things more manageable and structured we will use this project to contain all our template files and supporting code. After we have our project we add it as a ProjectTemplate asset ( this is done with source.extension.vsixmanifest
) in our VSIX project.
If your templates are so simple that they dont require anything additional you can just use a single VSIX project, add itself as an ProjectTemplate asset and place all exported zip files with the templates in a folder called ProjectTemplates in the root of the project.
Setting Up .vstemplate files
The essence of a Visual Studio project template is the xml file describing metadata, behavior and contents of the template. The base structure of the .vstemplate file looks something like this:
Simple structure with only those two elements <TemplateData>,<TemplateContent> and the attribute Type=”Project”
of the VSTemplate root element. Template Data describes what type of project it is and how Visual Studio has to handle it.
Another type of template we can create is a group template that essentially creates a Solution comprised of multiple .vstemplate files linked to the group one. Another useful thing we can add is a Wizard( this is described in the next chapter ) that gives you more interactivity with the project creation. A wizard can give you the ability to interact with a dialog before creation, access configurations from VS or make custom replacement of parameters.
This is an example group project template, as you can see its an ordinary project template, we added a Type=”ProjectGroup”
and <ProjectTemplateLink> elements contained in a <ProjectCollection>. Those element just link to the real templates that describe the projects in the group. You can also use <SolutionFolder> to customize how the solution is stored.
Template File Structure
Put simply every project template you want to add is a folder containing all the files and the .vstemplate file, the same way the “Export template” process generates files in the zip file. Using a group template should be added to the root so it can easily reference all project template folders.
Creating Project Template Wizards
Attaching a wizard to the project template gives you the ability to control how the contents of the template are generated. For example you can have a dialog with a couple of options and based on what the user selects to skip creating some files or replace with different parameters. All of this as simple as making an app with some forms in it and configuring it to the project template in the package. We can add a class to our existing project that holds the template or create a new project specifically for the wizard. Depending on what you do you should reference the appropriate assembly later on ( described further down ). After than we need to create our Wizard class that implements an IWizard interface. You should also add the following references to the project System.Windows Forms, EnvDTE and Microsoft.VisualStudio.TemplateWizardInterface
This simple implementation create a dialog window with WinForms where we input a custom message that we use as a replacement parameter. This happens by adding what input we got from the dialog into the replacementDictionary for our template.
Using WPF instead of WinForms for a dialog is also possible so i will link an example ( WPF Example code )
For the Wizard to be associated with a template we have to have an assembly included in the VSIX package that needs to be signed, because we need a fully qualified name for it.
Quick Steps for signing an assembly (make sure you are running VS as administrator ):
On the Assembly project ( the one creating an assembly ) go to Properties → Signing
. Add a new sign key ( shown bellow ), there is no need for password protection.
After Building the solution you will see a key.snk file generated, for convinience you can choose to copy the file to the build output dir. Open a Command Prompt and go to your output directory containing the Assembly we want to sign.
Find sn.exe on your system, its usually located in a path like this C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\sn.exe
(when you have a path with spaces dont forget to add quotes to run the executable )
3. Run the following commands ( dont forget to quote the path if it contains spaces )
“\sn.exe” -p key.snk outfile.key
“\sn.exe” -t outfile.key
If everything went well you should get an output like this “Public key token is
<WizardExtension>
<Assembly>RootTemplatePlaceholder, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=9a0a174492e9b787</Assembly>
<FullClassName>RootTemplatePlaceholder.TBBProjectWizard</FullClassName>
</WizardExtension>
Here you just set the proper Assembly version and the PublicKeyToken that we generate from the key.snk The main workhorse of the Wizard is the RunStarted method After clicking on Create in the project creation dialog the RunStarted method gets executed, that’s the perfect opportunity to make some changes or request input from the user.
Setting Parameters in templates
This is basically a string replacement in project template files that have the ReplaceParameters attribute in the .vstemplate set to true, so we also have the option to exclude files from the replacement. There are two ways of specifying parameters:
- Using the .vstemplate <CustomParameter>
- Using the RunStared method in a wizard to modify the replacementDictionary
Using <CustomParameter>:
Place a <CustomParameters> tag inside you template content element, this acts as a container for all the custom parameters. Each parameter has a name and a value. That means that every instance of the content of name will be replaced with the corresponding value. To differentiate from other text in the template files the notation with dollar sign at the start and end of the name is used.
<CustomParameters>
<CustomParameter Name="$color1$" Value="Red"/>
<CustomParameter Name="$color2$" Value="Blue "/>
</CustomParameters>
Also for convenience there are some reserved ones for basic project creation and naming that can be found here. Summary
- Create your project structure
- Export template
- Create VSIX and placeholder project
- Add templates to placeholder project
- Edit replacements and wizards
- Publish/Use
Conclusion
As a conclusion, try making your own templates have fun because all the work you put it will pay off in the long run. Maybe you want to create boilerplate project templates that help you test and experiment with a language feature or some framework :) , also learning how to do all of this i created my own project templates for making base projects for Thread Building Blocks, OpenCL (using the Nvidia SDK ) and OpenMP which you can find here.