将向导与项目模板配合使用
Visual Studio 提供了 IWizard 接口,可实现该接口来在用户从模板创建项目时运行自定义代码。
项目模板自定义可用于显示收集用户输入以自定义模板、向模板添加其他文件或项目允许的任何其他操作的自定义 UI。
在IWizard创建项目时,会在不同时间调用接口方法,一旦用户单击“新建项目”对话框中的“确定”,就会立即开始。 接口的每个方法都命名为描述调用接口的点。 例如,Visual Studio 在开始创建项目时立即调用 RunStarted ,使其成为编写自定义代码以收集用户输入的好位置。
使用 VSIX 项目创建项目模板项目
开始使用项目模板项目创建自定义模板,该项目是 Visual Studio SDK 的一部分。 在此过程中,我们将使用 C# 项目模板项目,但还有一个 Visual Basic 项目模板项目。 然后将 VSIX 项目添加到包含项目模板项目的解决方案。
创建 C# 项目模板项目(在 Visual Studio 中,选择“文件>新建>项目”并搜索“项目模板”)。 将其命名为 MyProjectTemplate。
注意
系统可能会要求你安装 Visual Studio SDK。 有关详细信息,请参阅安装 Visual Studio SDK。
在项目模板项目所在的同一解决方案中添加一个新的 VSIX 项目(在解决方案资源管理器中,选择解决方案节点,右键单击,然后选择“添加新>项目”并搜索“vsix”。 将其命名为 MyProjectWizard。
将 VSIX 项目设置为启动项目。 在解决方案资源管理器中,选择 VSIX 项目节点,右键单击并选择“设置为启动项目”。
将模板项目添加为 VSIX 项目的资产。 在解决方案资源管理器的 VSIX 项目节点下,找到 source.extension.vsixmanifest 文件。 双击它以在清单编辑器中打开它。
在清单编辑器中,选择 窗口左侧的“资产 ”选项卡。
在 “资产 ”选项卡中,选择“ 新建”。 在 “添加新资产 ”窗口中,对于“类型”字段,选择 “Microsoft.VisualStudio.ProjectTemplate”。 在 “源 ”字段中,选择 当前解决方案中的项目。 在 “项目 ”字段中,选择 “MyProjectTemplate”。 。
生成解决方案并开始调试。 将出现 Visual Studio 的第二个实例。 (这可能需要几分钟的时间。)
在 Visual Studio 的第二个实例中,尝试使用新模板创建新项目(文件>新建>项目,搜索“myproject”)。 新项目应与名为 Class1 的类一起显示。 现已创建自定义项目模板! 立即停止调试。
创建自定义模板向导
此过程演示如何创建一个在创建项目之前打开 Windows 窗体的自定义向导。 表单允许用户添加在项目创建过程中添加到源代码的自定义参数值。
设置 VSIX 项目以允许它创建程序集。
在解决方案资源管理器中,选择 VSIX 项目节点。 在解决方案资源管理器下方,应会看到“属性”窗口。 如果没有,请选择“查看>属性”窗口,或按 F4。 在 “属性” 窗口中,选择要执行以下操作的字段
true
:在 VSIX 容器中包含程序集
在本地 VSIX 部署中包含调试符号
在 VSIX 容器中包含调试符号
将程序集作为资产添加到 VSIX 项目。 打开 source.extension.vsixmanifest 文件,然后选择“资产”选项卡。在“添加新资产”窗口中,选择“Microsoft.VisualStudio.Assembly”、“源”选择当前解决方案中的“项目”和“项目”选择“MyProjectWizard”。
将以下引用添加到 VSIX 项目。 (In 解决方案资源管理器,在 VSIX 项目节点下,选择“引用”,右键单击并选择“添加引用”。在“添加引用”对话框中的“框架”选项卡中,找到 System.Windows 窗体 程序集并选择它。 还可以查找并选择 System.Drawing 程序集。 现在,选择“ 扩展 ”选项卡。找到 EnvDTE 程序集并选择它。 另请找到 Microsoft.VisualStudio.TemplateWizardInterface 程序集并选择它。 单击“确定”。
将向导实现的类添加到 VSIX 项目。 (In 解决方案资源管理器,右键单击 VSIX 项目节点,然后选择“添加”,然后选择“新建项”,然后选择“类”。将类命名为 WizardImplementation。
将 WizardImplementationClass.cs 文件中的代码替换为以下代码:
using System; using System.Collections.Generic; using Microsoft.VisualStudio.TemplateWizard; using System.Windows.Forms; using EnvDTE; namespace MyProjectWizard { public class WizardImplementation:IWizard { private UserInputForm inputForm; private string customMessage; // This method is called before opening any item that // has the OpenInEditor attribute. public void BeforeOpeningFile(ProjectItem projectItem) { } public void ProjectFinishedGenerating(Project project) { } // This method is only called for item templates, // not for project templates. public void ProjectItemFinishedGenerating(ProjectItem projectItem) { } // This method is called after the project is created. public void RunFinished() { } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { try { // Display a form to the user. The form collects // input for the custom message. inputForm = new UserInputForm(); inputForm.ShowDialog(); customMessage = UserInputForm.CustomMessage; // Add custom parameters. replacementsDictionary.Add("$custommessage$", customMessage); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } // This method is only called for item templates, // not for project templates. public bool ShouldAddProjectItem(string filePath) { return true; } } }
稍后将实现此代码中引用的 UserInputForm。
该
WizardImplementation
类包含每个成员 IWizard的方法实现。 在此示例中,只有 RunStarted 方法执行任务。 所有其他方法不执行任何操作或返回true
。该方法 RunStarted 接受四个参数:
一个 Dictionary<TKey,TValue> 参数,其中包含模板中所有预定义参数的集合。 有关模板参数的详细信息,请参阅 模板参数。
一个 WizardRunKind 参数,其中包含有关正在使用哪种类型的模板的信息。
一个 Object 数组,其中包含由 Visual Studio 传递给向导的一组参数。
本示例将用户输入表单中的参数值添加到 Dictionary<TKey,TValue> 参数。 项目中的参数的每个实例
$custommessage$
都将替换为用户输入的文本。
现在创建 UserInputForm。 在 WizardImplementation.cs 文件中,在类末尾
WizardImplementation
添加以下代码。public partial class UserInputForm : Form { private static string customMessage; private TextBox textBox1; private Button button1; public UserInputForm() { this.Size = new System.Drawing.Size(155, 265); button1 = new Button(); button1.Location = new System.Drawing.Point(90, 25); button1.Size = new System.Drawing.Size(50, 25); button1.Click += button1_Click; this.Controls.Add(button1); textBox1 = new TextBox(); textBox1.Location = new System.Drawing.Point(10, 25); textBox1.Size = new System.Drawing.Size(70, 20); this.Controls.Add(textBox1); } public static string CustomMessage { get { return customMessage; } set { customMessage = value; } } private void button1_Click(object sender, EventArgs e) { customMessage = textBox1.Text; this.Close(); } }
用户输入窗体提供用于输入自定义参数的简单窗体。 窗体包含一
textBox1
个名为文本框和一个名为按钮的button1
文本框。 单击按钮后,文本框中的文本将存储在参数中customMessage
。
将向导连接自定义模板
为了使自定义项目模板使用自定义向导,需要对向导程序集进行签名,并将一些行添加到自定义项目模板,以便告知在创建新项目时在何处查找向导实现。
对程序集进行签名。 在解决方案资源管理器中,选择 VSIX 项目,右键单击并选择“项目属性”。
在“项目属性”窗口中,选择“签名”选项卡。在“签名”选项卡中,检查对程序集进行签名。 在 “选择强名称密钥文件 ”字段中,选择“ <新建>”。 在“创建强名称密钥”窗口中的“密钥文件名”字段中,键入 key.snk。 取消检查使用密码字段保护密钥文件。
在解决方案资源管理器中,选择 VSIX 项目并找到“属性”窗口。
将 “复制生成输出”字段设置为 true。 这允许在重新生成解决方案时将程序集复制到输出目录中。 该文件仍包含在
.vsix
文件中。 需要查看程序集才能找出其签名密钥。重新生成解决方案。
现在可以在 MyProjectWizard 项目目录中找到 key.snk 文件(<磁盘位置>\MyProjectTemplate\MyProjectWizard\key.snk)。 复制 key.snk 文件。
转到输出目录并查找程序集(<磁盘位置>\MyProjectTemplate/MyProjectWizard\bin\Debug\MyProjectWizard.dll)。 在此处粘贴 key.snk 文件。 (这不是绝对必要的,但它将使以下步骤更容易。
打开命令窗口,并更改为在其中创建了程序集的目录。
查找 sn.exe 签名工具。 例如,在 Windows 10 64 位操作系统上,典型的路径如下:
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools
如果找不到该工具,请尝试在命令窗口中运行 /R . sn.exe 的位置。 记下路径。
从 key.snk 文件中提取公钥。 在命令窗口中,键入
<sn.exe>\sn.exe -p key.snk outfile.key 的位置。
如果目录名称中有空格,请不要忘记用引号括住 sn.exe 的路径!
从 outfile 获取公钥令牌:
<sn.exe>\sn.exe -t outfile.key 的位置。
同样,不要忘记引号。 应会看到输出中的一行,如下所示
公钥令牌是 <令牌>
记下此值。
将对自定义向导的引用添加到 项目模板的 .vstemplate 文件。 在解决方案资源管理器中,找到名为 MyProjectTemplate.vstemplate 的文件,然后打开它。 在 TemplateContent> 节结束时<,添加以下部分:
<WizardExtension> <Assembly>MyProjectWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=token</Assembly> <FullClassName>MyProjectWizard.WizardImplementation</FullClassName> </WizardExtension>
其中 MyProjectWizard 是程序集的名称,令牌是你在上一步中复制的令牌。
保存项目中的所有文件并重新生成。
将自定义参数添加到模板
在此示例中,用作模板的项目显示自定义向导的用户输入表单中指定的消息。
在解决方案资源管理器中,转到 MyProjectTemplate 项目并打开 Class1.cs。
在
Main
应用程序的方法中,添加以下代码行。Console.WriteLine("$custommessage$");
$custommessage$
从模板创建项目时,参数将替换为在用户输入表单中输入的文本。
下面是导出到模板之前的完整代码文件。
using System;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ >= 3.5)using System.Linq;
$endif$using System.Text;
namespace $safeprojectname$
{
public class Class1
{
static void Main(string[] args)
{
Console.WriteLine("$custommessage$");
}
}
}
使用自定义向导
现在,可以从模板创建项目并使用自定义向导。
重新生成解决方案并开始调试。 将显示 Visual Studio 的第二个实例。
创建新的 MyProjectTemplate 项目。 (文件>新建>项目)。
在 “新建项目 ”对话框中,搜索“myproject”以找到模板,键入名称,然后单击“ 确定”。
此时会打开向导用户输入表单。
键入自定义参数的值,然后单击该按钮。
向导用户输入表单将关闭,并从模板创建项目。
在解决方案资源管理器中,右键单击源代码文件,然后单击“查看代码”。
请注意,
$custommessage$
已替换为向导用户输入表单中输入的文本。