ProjectTemplateTutorial
A tutorial on how to create a project template for Visual Studio.
Install / Use
/learn @dogtail9/ProjectTemplateTutorialREADME
Project Template Tutorial
This is a tutorial on how to create a project template for Visual Studio with multiple projects, commands, dialogs and external tools. The project template will have a mandatory and an optional project that you can choose from a dialog when the project is created. There will also be an item template that uses Text Template Transformation Toolkit (T4) to generate code from a DSL.
Step 0 : Prerequisites
I have the following softwares installed on my machine.
- Visual Studio 2015 Update 1
- Visual Studio SDK
- Extensibility Tools for Visual Studio
- ILSyp
If you download the code from GitHub you have to change the debug settings for the VSIXProject to be able to debug.
- Start Action : C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
- Command line arguments: /rootsuffix EXP
Change the debug settings for the VSIXProject when downloaded the code from GitHub
If you want to skip some steps in this tutorial, you can download the code and begin on the following steps
- Step 2 : Mandatory project template
- Step 3 : Optional project template
- Step 4 : NuGet packages
- Step 5 : Commands
- Step 6 : Create a custom item template
- Step 7 : Refactor some code to a reusable helper library
Step 1 : Create a custom project template
In the first step, we will create a VSIX Project, add a project template with a wizard (the SolutionWizard), where we by code could add other project templates to the solution.
Solution
First we need a solution. Open Visual Studio and follow the steps bellow.
Choose the blank solution project template
Now we have our solution that we can start adding project to.
VSIX Project
The VSIX project where we will put all logic such as wizards, commands and dialogs.
Add a VSIX Project to the solution
Delete the unnecessary files
Add folders for Commands, Dialogs and Wizards
Solution Project Template
Add a project template whose sole purpose is to run a wizard where we can add the code to create our project. I add all my template projects to a solution folder called ProjectTemplates.
Add the solution project template
Delete the unnecessary files
<Project File="ProjectTemplate.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="Properties\AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" OpenInEditor="true">Class1.cs</ProjectItem>
</Project>
Delete the content of the TemplateContent element in the ProjectTemplateTutorial.Solution.vstemplate file
Change the type attribute of the VSTemplate element in the vstemplate file to ProjectGroup
Add a category for the project template in the new project dialog
Solution wizard
Now we need to add a wizard class with the logic for creating our project template. Add a class to the Wizard folder in the VSIXProject, name it SolutionWizard. The SolutionWizard class should implement the IWizard interface. You also need to sign all projects in the solution.
Add the references to envdte and Microsoft.VisualStudio.TemplateWizardInterface in the VSIXProject
using Microsoft.VisualStudio.TemplateWizard;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
namespace ProjectTemplateTutorial.VSIXProject.Wizards
{
public class SolutionWizard : IWizard
{
public void BeforeOpeningFile(ProjectItem projectItem)
{
}
public void ProjectFinishedGenerating(Project project)
{
}
public void ProjectItemFinishedGenerating(ProjectItem projectItem)
{
}
public void RunFinished()
{
int i = 0;
}
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
}
public bool ShouldAddProjectItem(string filePath) => true;
}
}
The SolutionWizard class
Set a breakpoint in the int i = 0; line in the RunFinished method.
Assets
The only thing left to do is to add assets to the VSIXProject. Open the source.extension.vsixmanifest file in the VSIXProject. Add the assets below.
Add assembly
Add project template
Add the wizard to the solution project template
I use ILSpy to get the strongname of the ProjectTemplate.VSIXProject.dll
<WizardExtension>
<Assembly>ProjectTemplateTutorial.VSIXProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b490d4518b7bc751</Assembly>
<FullClassName> ProjectTemplateTutorial.VSIXProject.Wizards.SolutionWizard</FullClassName>
</WizardExtension>
Add the WizardExtension element to VSTemplate element in the vstemplate file
Let´s try to create a project with our project template.
The project template is located in the tutorial category in the New Project dialog
The break point in the RunFinished method should be hit
An empty solution is created
We are done with the first step in this tutorial.
Step 2 : Mandatory project template
Let´s add the project template for the mandatory project. If you skiped the first step in this tutorial you can download the code from the Solution release and start the tutorial here.
Add the mandatory project template
We want to hide this project template in the New Project dialog and add the project to the solution from the SolutionWizard class.
<Hidden>true</Hidden>
Add the Hidden element to the TemplateData element in the ProjectTemplateTutorial.Mandatory.vstemplate file
Add the mandatory project template as an asset in the VSIXproject
Add the Microsoft.VisualStudio.Shell.14.0 NuGet package to the VSIXProject
Let's write the code to add the mandatory project to the solution. Visual Studio passes a dictionary with data from the New Project dialog to the wizard. We need to save this data and use it to create the mandatory project from our mandatory project template.
private Dictionary<string, string> _replacementsDictionary = new Dictionary<string, string>();
DTE _dte;
public SolutionWizard()
{
_dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE;
}
Add a constructor and fields to the SolutionWizard class
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
_replacementsDictionary = replacementsDictionary;
}
Store the replacementsDictionary in the field in the RunStarted method
public void RunFinished()
{
string destination = _replacementsDictionary["$destinationdirectory$"];
string fileName = _replacementsDictionary["$safeprojectname$"] + ".sln";
_dte.Solution.SaveAs(Path.Combine(destination, fileName));
var projectName = $"{_replacementsDictionary["$safeprojectname$"]}.Mandatory";
var templateName = "ProjectTemplateTutorial.Mandatory";
AddProject(destination, projectName, templateName);
}
Get the data for our project from the replacementsDictionary and pass it to the AddProject method
We will use the DTE object to add the project to our solution. Later we will refactor this method to a helper library so we can reuse it in other project templates but for now just put the AddProject method in the SolusionWizard class.
private void AddProject(string destination, string projectName, string templateName)
{
string projectPath = Path.Combine(destination, projectName);
string templatePath = ((Solution4)_dte.Solution).GetProjectTemplate(templateName, "cs");
_dte.Solution.AddFromTemplate(templatePath, projectPath, projectName, false);
}
Code to add the a project to the solution
Let's try the project template to see it the mandatory project is created.
The mandatory project is created
You can also add projects and use the build in project template if you like. You find the build in project templates in the C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\ProjectTemplates folder.
projectName = $"{_replacementsDictionary["$safeprojectname$"]}.WCFServiceLibrary";
AddProject(destination, projectName, "WcfServiceLibrary");
Add a WCFServiceLibrary to the solution
*The project cr
Related Skills
node-connect
351.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
110.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
351.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
351.2kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
