将向导与项目模板配合使用

Visual Studio 提供了 IWizard 接口,可实现该接口来在用户从模板创建项目时运行自定义代码。

项目模板自定义可用于显示收集用户输入以自定义模板、向模板添加其他文件或项目允许的任何其他操作的自定义 UI。

IWizard创建项目时,会在不同时间调用接口方法,一旦用户单击“新建项目”对话框中的“确定”,就会立即开始。 接口的每个方法都命名为描述调用接口的点。 例如,Visual Studio 在开始创建项目时立即调用 RunStarted ,使其成为编写自定义代码以收集用户输入的好位置。

使用 VSIX 项目创建项目模板项目

开始使用项目模板项目创建自定义模板,该项目是 Visual Studio SDK 的一部分。 在此过程中,我们将使用 C# 项目模板项目,但还有一个 Visual Basic 项目模板项目。 然后将 VSIX 项目添加到包含项目模板项目的解决方案。

  1. 创建 C# 项目模板项目(在 Visual Studio 中,选择“文件>新建>项目”并搜索“项目模板”)。 将其命名为 MyProjectTemplate

    注意

    系统可能会要求你安装 Visual Studio SDK。 有关详细信息,请参阅安装 Visual Studio SDK

  2. 在项目模板项目所在的同一解决方案中添加一个新的 VSIX 项目(在解决方案资源管理器中,选择解决方案节点,右键单击,然后选择“添加新>项目”并搜索“vsix”。 将其命名为 MyProjectWizard。

  3. 将 VSIX 项目设置为启动项目。 在解决方案资源管理器中,选择 VSIX 项目节点,右键单击并选择“设置为启动项目”。

  4. 将模板项目添加为 VSIX 项目的资产。 在解决方案资源管理器的 VSIX 项目节点下,找到 source.extension.vsixmanifest 文件。 双击它以在清单编辑器中打开它。

  5. 在清单编辑器中,选择 窗口左侧的“资产 ”选项卡。

  6. “资产 ”选项卡中,选择“ 新建”。 在 “添加新资产 ”窗口中,对于“类型”字段,选择 “Microsoft.VisualStudio.ProjectTemplate”。 在 “源 ”字段中,选择 当前解决方案中的项目。 在 “项目 ”字段中,选择 “MyProjectTemplate”。 。

  7. 生成解决方案并开始调试。 将出现 Visual Studio 的第二个实例。 (这可能需要几分钟的时间。)

  8. 在 Visual Studio 的第二个实例中,尝试使用新模板创建新项目(文件>新建>项目,搜索“myproject”)。 新项目应与名为 Class1 的类一起显示。 现已创建自定义项目模板! 立即停止调试。

创建自定义模板向导

此过程演示如何创建一个在创建项目之前打开 Windows 窗体的自定义向导。 表单允许用户添加在项目创建过程中添加到源代码的自定义参数值。

  1. 设置 VSIX 项目以允许它创建程序集。

  2. 解决方案资源管理器中,选择 VSIX 项目节点。 在解决方案资源管理器下方,应会看到“属性”窗口。 如果没有,请选择“查看>属性”窗口,或按 F4。“属性” 窗口中,选择要执行以下操作的字段 true

    • 在 VSIX 容器中包含程序集

    • 在本地 VSIX 部署中包含调试符号

    • 在 VSIX 容器中包含调试符号

  3. 将程序集作为资产添加到 VSIX 项目。 打开 source.extension.vsixmanifest 文件,然后选择“资产”选项卡。在“添加新资产”窗口中,选择Microsoft.VisualStudio.Assembly”、“源”选择当前解决方案中的“项目”和“项目”选择“MyProjectWizard”。

  4. 将以下引用添加到 VSIX 项目。 (In 解决方案资源管理器,在 VSIX 项目节点下,选择“引用,右键单击并选择“添加引用”。在“添加引用”对话框中的“框架”选项卡中,找到 System.Windows 窗体 程序集并选择它。 还可以查找并选择 System.Drawing 程序集。 现在,选择“ 扩展 ”选项卡。找到 EnvDTE 程序集并选择它。 另请找到 Microsoft.VisualStudio.TemplateWizardInterface 程序集并选择它。 单击“确定”。

  5. 将向导实现的类添加到 VSIX 项目。 (In 解决方案资源管理器,右键单击 VSIX 项目节点,然后选择“添加”,然后选择“新建项”,然后选择”。将类命名为 WizardImplementation

  6. 将 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 接受四个参数:

    • Object可强制转换为根_DTE对象的参数,用于自定义项目。

    • 一个 Dictionary<TKey,TValue> 参数,其中包含模板中所有预定义参数的集合。 有关模板参数的详细信息,请参阅 模板参数

    • 一个 WizardRunKind 参数,其中包含有关正在使用哪种类型的模板的信息。

    • 一个 Object 数组,其中包含由 Visual Studio 传递给向导的一组参数。

      本示例将用户输入表单中的参数值添加到 Dictionary<TKey,TValue> 参数。 项目中的参数的每个实例 $custommessage$ 都将替换为用户输入的文本。

  7. 现在创建 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

将向导连接自定义模板

为了使自定义项目模板使用自定义向导,需要对向导程序集进行签名,并将一些行添加到自定义项目模板,以便告知在创建新项目时在何处查找向导实现。

  1. 对程序集进行签名。 在解决方案资源管理器中,选择 VSIX 项目,右键单击并选择“项目属性”。

  2. “项目属性”窗口中,选择“签名”选项卡。在“签名”选项卡中,检查对程序集进行签名。 在 “选择强名称密钥文件 ”字段中,选择“ <新建>”。 在“创建强名称密钥”窗口中的“密钥文件名”字段中,键入 key.snk。 取消检查使用密码字段保护密钥文件。

  3. 解决方案资源管理器中,选择 VSIX 项目并找到“属性”窗口。

  4. “复制生成输出”字段设置为true。 这允许在重新生成解决方案时将程序集复制到输出目录中。 该文件仍包含在 .vsix 文件中。 需要查看程序集才能找出其签名密钥。

  5. 重新生成解决方案。

  6. 现在可以在 MyProjectWizard 项目目录中找到 key.snk 文件(<磁盘位置>\MyProjectTemplate\MyProjectWizard\key.snk)。 复制 key.snk 文件。

  7. 转到输出目录并查找程序集(<磁盘位置>\MyProjectTemplate/MyProjectWizard\bin\Debug\MyProjectWizard.dll)。 在此处粘贴 key.snk 文件。 (这不是绝对必要的,但它将使以下步骤更容易。

  8. 打开命令窗口,并更改为在其中创建了程序集的目录。

  9. 查找 sn.exe 签名工具。 例如,在 Windows 10 64 位操作系统上,典型的路径如下:

    C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools

    如果找不到该工具,请尝试在命令窗口中运行 /R . sn.exe 的位置。 记下路径。

  10. key.snk 文件中提取公钥。 在命令窗口中,键入

    <sn.exe>\sn.exe -p key.snk outfile.key 的位置。

    如果目录名称中有空格,请不要忘记用引号括住 sn.exe 的路径

  11. 从 outfile 获取公钥令牌:

    <sn.exe>\sn.exe -t outfile.key 的位置。

    同样,不要忘记引号。 应会看到输出中的一行,如下所示

    公钥令牌是 <令牌>

    记下此值。

  12. 将对自定义向导的引用添加到 项目模板的 .vstemplate 文件。 在解决方案资源管理器中,找到名为 MyProjectTemplate.vstemplate 的文件,然后打开它。 在 TemplateContent> 节结束时<,添加以下部分:

    <WizardExtension>
        <Assembly>MyProjectWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=token</Assembly>
        <FullClassName>MyProjectWizard.WizardImplementation</FullClassName>
    </WizardExtension>
    

    其中 MyProjectWizard 是程序集的名称,令牌是你在上一步中复制的令牌。

  13. 保存项目中的所有文件并重新生成。

将自定义参数添加到模板

在此示例中,用作模板的项目显示自定义向导的用户输入表单中指定的消息。

  1. 解决方案资源管理器中,转到 MyProjectTemplate 项目并打开 Class1.cs

  2. 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$");
          }
    }
}

使用自定义向导

现在,可以从模板创建项目并使用自定义向导。

  1. 重新生成解决方案并开始调试。 将显示 Visual Studio 的第二个实例。

  2. 创建新的 MyProjectTemplate 项目。 (文件>新建>项目)。

  3. “新建项目 ”对话框中,搜索“myproject”以找到模板,键入名称,然后单击“ 确定”。

    此时会打开向导用户输入表单。

  4. 键入自定义参数的值,然后单击该按钮。

    向导用户输入表单将关闭,并从模板创建项目。

  5. 解决方案资源管理器中,右键单击源代码文件,然后单击“查看代码”。

    请注意, $custommessage$ 已替换为向导用户输入表单中输入的文本。