[Visual Studio] 建立Project Wizard

有時建立Project 或Item 時, 除了預設名字外, 可能有需要加入更多的參數(Parameter)讓development 更方便, 在Project / item 生成後不用走入去再修改. 在這裡, 會示範如何在Project Template 中加入Wizard.

  1. 先找來一個Project Temple, 為方便示範, 故直接建立一個Project Template.
    按File->New->Project, 選擇Installed->Templates->Visual C#->Extensibility, 選取C# Project Template. 在是次示範, Project 命名為TestProjectTemplate.
  2. 於Project Template 中建立一個VSIX Project 作Wizard.
    按File->New->Project, 選擇Installed->Templates->Visual C#->Extensibility, 選取VSIX Project. 在是次示範, Project 命名為ProjectWizard.
  3. 將ProjectWizard 設為Startup Project.
    於ProjectWizard 右按, 選取Set as StartUp Project.
  4. 加入Project Template 作 VSIX asset.
    開啟source.extension.vsixmanifest, 選取Asset, 按New, 於Type 中選擇Microsoft.VisualStudio.ProjectTemplate, Source 選擇A project in current solution, 於Project 中選擇TestProjectTemplate. 然後按OK.
  5. 於ProjectWizard 中, 選擇Property, 並將以下設定改為True.
    Copy Build Output to Output Directory;
    Copy Debug Symbol to Output Directory;
    Include Assembly in VSIX Container;
    Include Debug Symbols in Local Deployment;
    Include Debug Symbols in CSIZ Container;
  6. 將ProjectWizard 加到Asset 中, 使在project create 時能夠透過XML call. 
    開啟source.extension.vsixmanifest, 選取Asset, 按New, 於Type 中選擇Microsoft.VisualStudio.Assembly, Source 選擇A project in current solution, 於Project 中選擇ProjectWizard. 然後按OK.
  7. 於ProjectWizard 中建立一個class, 命名為WizardImplementation, 並貼上以以下的code.
    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;  
            }          
        }
  8. 於ProjectWizard 中建立另一個class名為UserInputForm, 作為Wizard 的UI.
    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.Text = "Add text here.";
                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();
            }
        }
  9. 建立Key作Template與Project 的聯繫. 於ProjectWizard Property 中, 選取Signing, 剔取Sign the assembly, 並於Choose a strong name key file 中選擇<<New…>>
  10. 開始建立key. 於Key file name 中輸入key.sln, 剔除Protect my key file with a password, Signature Algronithrom 選取SHA256RAS 後按OK.
  11. 將key.sln 複制到/bin/debug 內.
  12. 開啟Visual Studio Command Prompt, 再去到<<Project folder>>/ bin/debug 中執行以下指令.
    ### Generate Public Key.
    sn.exe - p key.snk outfile.key
    
    ### Get Public key token and export STDOUT to text file.
    sn.exe - t outfile.key > c:\STDOUT.txt
  13. 於TestProjectTemplate 中開啟TestProjectTemplate.vstemplate, 並於<TemplateContent>後加入以下element, 決定建立Project 時會call 的wizard. 而[[token]] 是於STDOUT.txt 中export 出來的value.
    <WizardExtension>  
        <Assembly>ProjectWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=[[token]]</Assembly>  
        <FullClassName>ProjectWizard.WizardImplementation</FullClassName>  
    </WizardExtension>
  14. 於TestProjectTemplate 中開啟Class1.cs, 並修改以下內容.
    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$");  
              }  
        }  
    }
  15. 之後開始Debug, 之後會開一個新的Visual Studio Instance, 選擇New Project.
  16. 於Visual C# 中選取TestProjectTemplate, 然後按OK.
  17. 之前建立的UserInputForm 便會彈出, 輸入資料後按Add
  18. Porject 建立後, 開啟Class1.cs, 見到剛才輸入的字句的話, 測試成功.

Reference

About C.H. Ling 262 Articles
a .net / Java developer from Hong Kong and currently located in United Kingdom. Thanks for Google because it solve many technical problems so I build this blog as return. Besides coding and trying advance technology, hiking and traveling is other favorite to me, so I will write down something what I see and what I feel during it. Happy reading!!!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.