建立基本的專案系統,第 2 部分
本系列的第一個逐步解說:建立基本專案系統第 1 部分說明如何建立基本專案系統。 本逐步解說以基本專案系統為基礎建置,新增 Visual Studio 範本、屬性頁和其他功能。 在開始本逐步解說之前,必須完成第一個逐步解說。
本逐步解說教導如何建立專案副檔名 .myproj 的專案類型。 若要完成逐步解說,您不需要建立自己的語言,因為逐步解說會借用現有的 Visual C# 專案系統。
本逐步解說教導如何完成以下任務:
建立 Visual Studio 範本。
部署 Visual Studio 範本。
在 [新增專案] 對話方塊中建立專案類型子節點。
在 Visual Studio 範本中啟用參數替代。
建立專案屬性頁。
注意
本逐步解說中的步驟是以 C# 專案為基礎。 不過,除了副檔名和程式碼等細節之外,您也可以將相同的步驟用於 Visual Basic 專案。
建立 Visual Studio 範本
- 建立基本專案系統,第 1 部分說明如何建立基本專案範本,並將其新增至專案系統。 文中也說明如何使用 ProvideProjectFactoryAttribute 屬性向 Visual Studio 註冊此範本,這會在系統登錄中寫入 \Templates\Projects\SimpleProject\ 資料夾的完整路徑。
藉由使用 Visual Studio 範本 (.vstemplate 檔案) 而不是基本專案範本,您可以控制範本在 [新增專案] 對話方塊中的顯示方式,以及範本參數的替代方式。 .vstemplate 檔案是 XML 檔案,描述使用專案系統範本建立專案時要如何包含來源檔案。 專案系統本身是藉由收集 .vstemplate 檔案和 .zip 檔案中的來源檔案來建置,並將 .zip 檔案複製到 Visual Studio 已知的位置來部署。 本逐步解說稍後會更詳細地說明此程序。
在 Visual Studio 中,開啟您遵循建立基本專案系統第 1 部分所建立的 SimpleProject 方案。
在 SimpleProjectPackage.cs 檔案中,尋找 ProvideProjectFactory 屬性。 將第二個參數 (專案名稱) 取代為 null,並將第四個參數 (專案範本資料夾的路徑) 取代為 “.\\NullPath”,如下所示。
[ProvideProjectFactory(typeof(SimpleProjectFactory), null, "Simple Project Files (*.myproj);*.myproj", "myproj", "myproj", ".\\NullPath", LanguageVsTemplate = "SimpleProject")]
將名為 SimpleProject.vstemplate 的 XML 檔案新增至 \Templates\Projects\SimpleProject\ 資料夾。
以下列程式碼取代 SimpleProject.vstemplate 的內容:
<VSTemplate Version="2.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"> <TemplateData> <Name>SimpleProject Application</Name> <Description> A project for creating a SimpleProject application </Description> <Icon>SimpleProject.ico</Icon> <ProjectType>SimpleProject</ProjectType> </TemplateData> <TemplateContent> <Project File="SimpleProject.myproj" ReplaceParameters="true"> <ProjectItem ReplaceParameters="true" OpenInEditor="true"> Program.cs </ProjectItem> <ProjectItem ReplaceParameters="true" OpenInEditor="false"> AssemblyInfo.cs </ProjectItem> </Project> </TemplateContent> </VSTemplate>
在 [屬性] 視窗中,選取 \Templates\Projects\SimpleProject\ 資料夾中的所有五個檔案,並將 [建置動作] 設定為 [ZipProject]。
<TemplateData> 區段會決定 [新增專案] 對話方塊中 SimpleProject 專案類型的位置和外觀,如下所示:
<Name> 元素會將專案範本命名為 SimpleProject Application。
<Description> 元素包含選取專案範本時出現在 [新增專案] 對話方塊中的描述。
<Icon> 元素會指定與 SimpleProject 專案類型一起出現的圖示。
<ProjectType> 元素會在 [新增專案] 對話方塊中命名專案類型。 此名稱會取代 ProvideProjectFactory 屬性的專案名稱參數。
注意
<ProjectType> 元素必須符合 SimpleProjectPackage.cs 檔案中
ProvideProjectFactory
屬性的LanguageVsTemplate
引數。<TemplateContent> 區段描述建立新專案時產生的這些檔案:
SimpleProject.myproj
Program.cs
AssemblyInfo.cs
這三個檔案都將
ReplaceParameters
設定為 true,以啟用參數替代。 Program.cs 檔案將OpenInEditor
設定為 true,這會在建立專案時,於程式碼編輯器中開啟檔案。如需 Visual Studio 範本結構描述中元素的詳細資訊,請參閱 Visual Studio 範本結構描述參考。
注意
如果專案有多個 Visual Studio 範本,每個範本都會位於個別的資料夾中。 該資料夾中的每個檔案都必須將 [建置動作] 設定為 [ZipProject]。
新增最基本的 .vsct 檔案
Visual Studio 必須在安裝模式中執行,才能辨識新的或修改過的 Visual Studio 範本。 安裝模式需要有 .vsct 檔案。 因此,您必須將最基本的 .vsct 檔案新增至專案。
將名為 SimpleProject.vsct 的 XML 檔案新增至 SimpleProject 專案。
以下列程式碼取代 SimpleProject.vsct 檔案的內容:
<?xml version="1.0" encoding="utf-8" ?> <CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable"> </CommandTable>
將此檔案的 [建置動作] 設定為 [VSCTCompile]。 您只能在 .csproj 檔案中執行這項操作,而不是在 [屬性] 視窗中。 請確定此檔案的 [建置動作] 此時設定為 [無]。
以滑鼠右鍵按一下 SimpleProject 節點,然後按一下 [編輯 SimpleProject.csproj]。
在 .csproj 檔案中,找出 SimpleProject.vsct 專案。
<None Include="SimpleProject.vsct" />
將建置動作變更為 [VSCTCompile]。
<VSCTCompile Include="SimpleProject.vsct" />
儲存專案檔案並關閉編輯器。
儲存 SimpleProject 節點,然後在 [方案總管] 中按一下 [重新載入專案]。
檢查 Visual Studio 範本建置步驟
當 .vstemplate 檔案發生變更或重建包含 .vstemplate 檔案的專案時,VSPackage 專案建置系統通常會在安裝模式中執行 Visual Studio。 您跟著做,將 MSBuild 的詳細程度等級設定為 [一般] 或更高。
在 [工具] 功能表上,按一下 [選項] 。
展開 [專案和解決方案] 節點,然後選擇 [建置並執行]。
將 [MSBuild 專案建置輸出詳細程度] 設定為 [一般]。 按一下 [確定]。
重建 SimpleProject 專案。
建立 .zip 專案檔的建置步驟應該類似如下範例。
ZipProjects:
1> Zipping ProjectTemplates
1> Zipping <path>\SimpleProject\SimpleProject\obj\Debug\SimpleProject.zip...
1> Copying file from "<path>\SimpleProject\SimpleProject\obj\Debug\SimpleProject.zip" to "<%LOCALAPPDATA%>\Microsoft\VisualStudio\14.0Exp\ProjectTemplates\\\\SimpleProject.zip".
1> Copying file from "<path>\SimpleProject\SimpleProject\obj\Debug\SimpleProject.zip" to "bin\Debug\\ProjectTemplates\\\\SimpleProject.zip".
1> SimpleProject -> <path>\SimpleProject\SimpleProject\bin\Debug\ProjectTemplates\SimpleProject.zip
1>ZipItems:
1> Zipping ItemTemplates
1> SimpleProject ->
部署 Visual Studio 範本
Visual Studio 範本不包含路徑資訊。 因此,範本 .zip 檔案必須部署到 Visual Studio 已知的位置。 ProjectTemplates 資料夾的位置通常是 <%LOCALAPPDATA%>\Microsoft\VisualStudio\14.0Exp\ProjectTemplates。
若要部署您的專案處理站,安裝程式必須具有系統管理員權限。 它會將範本部署在 Visual Studio 安裝節點下:...\Microsoft Visual Studio 14.0\Common7\IDE\ProjectTemplates。
測試 Visual Studio 範本
測試您的專案處理站,查看它是否使用 Visual Studio 範本建立專案階層。
重設 Visual Studio SDK 實驗執行個體。
在 Windows 7:在 [開始] 功能表上,尋找 [Microsoft Visual Studio/Microsoft Visual Studio SDK/Tools] 資料夾,然後選取 [重設 Microsoft Visual Studio 實驗執行個體]。
在更新版本的 Windows 上:在 [開始] 畫面上,輸入重設 Microsoft Visual Studio <版本>實驗執行個體。
隨即出現命令提示字元視窗。 當您看到 [按任意鍵繼續] 文字時,按一下 ENTER。 視窗關閉之後,開啟 Visual Studio。
重建 SimpleProject 專案並開始偵錯。 隨即出現實驗執行個體。
在實驗執行個體中,建立 SimpleProject 專案。 在 [新增專案] 對話方塊中,選取 [SimpleProject]。
您應該會看到 SimpleProject 的新執行個體。
建立專案類型子節點
您可以在 [新增專案] 對話方塊中,將子節點新增至專案類型節點。 例如,針對 SimpleProject 專案類型,您可以有主控台應用程式的子節點、視窗應用程式、Web 應用程式等等。
子節點的建立方式是更改專案檔,並將 <OutputSubPath> 子系新增至 <ZipProject> 元素。 在建置或部署期間複製範本時,每個子節點都會變成專案範本資料夾的子資料夾。
本節說明如何建立 SimpleProject 專案類型的主控台子節點。
將 \Templates\Projects\SimpleProject\ 資料夾重新命名為 \Templates\Projects\ConsoleApp\。
在 [屬性] 視窗中,選取 \Templates\Projects\ConsoleApp\ 資料夾中全部五個檔案,並確定 [建置動作] 已設定為 [ZipProject]。
在 SimpleProject.vstemplate 檔案中,於 <TemplateData> 區段結尾處新增下一行,就在結尾標記之前。
<NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp>
這會導致主控台應用程式範本同時出現在主控台子節點和 SimpleProject 父節點中,也就是子節點的上一層。
儲存 SimpleProject.vstemplate 檔案。
在 .csproj 檔案中,將 <OutputSubPath> 新增至每個 ZipProject 元素。 如先前一樣卸載專案,然後編輯專案檔。
找出 <ZipProject> 元素。 針對每個 <ZipProject> 元素,新增 <OutputSubPath> 元素,並將值設為 Console。 ZipProject
<ZipProject Include="Templates\Projects\ConsoleApp\AssemblyInfo.cs"> <OutputSubPath>Console</OutputSubPath> </ZipProject> <ZipProject Include="Templates\Projects\ConsoleApp\Program.cs"> <OutputSubPath>Console</OutputSubPath> </ZipProject> <ZipProject Include="Templates\Projects\ConsoleApp\SimpleProject.myproj"> <OutputSubPath>Console</OutputSubPath> </ZipProject> <ZipProject Include="Templates\Projects\ConsoleApp\SimpleProject.vstemplate"> <OutputSubPath>Console</OutputSubPath> </ZipProject> <ZipProject Include="Templates\Projects\ConsoleApp\SimpleProject.ico"> <OutputSubPath>Console</OutputSubPath> </ZipProject>
將此 <PropertyGroup> 新增到專案檔:
<PropertyGroup> <VsTemplateLanguage>SimpleProject</VsTemplateLanguage> </PropertyGroup>
儲存專案檔並重新載入專案。
測試專案類型子節點
測試修改過的專案檔,查看 Console 子節點是否出現在 [新增專案] 對話方塊中。
執行「重設 Microsoft Visual Studio 實驗執行個體」工具。
重建 SimpleProject 專案並開始偵錯。 應該會出現實驗執行個體
在 [新增專案] 對話方塊中,按一下 [SimpleProject] 節點。 [主控台應用程式] 範本應該會出現在 [範本] 窗格中。
展開 [SimpleProject] 節點。 應該會出現 [主控台] 子節點。 [SimpleProject 應用程式]範本會繼續出現在 [範本] 窗格中。
按一下 [取消] 並停止偵錯。
替代專案範本參數
- 建立基本專案系統,第 1 部分說明了如何覆寫
ProjectNode.AddFileFromTemplate
方法,以執行基本類型的範本參數替代。 本節將教導如何使用更複雜的 Visual Studio 範本參數。
當您在 [新增專案] 對話方塊中使用 Visual Studio 範本建立專案時,範本參數會取代為字串來自訂專案。 範本參數是一種特殊的權杖,開頭和結尾是貨幣符號,例如,$time$。 下列兩個參數特別適用於在以範本為基礎的專案中啟用自訂:
$GUID[1-10]$ 會以新的 Guid 取代。 您最多可以指定 10 個唯一的 GUID,例如,$guid1$。
$safeprojectname$ 是使用者在 [新增專案] 對話方塊中提供的名稱,已經過修改以移除所有不安全的字元和空格。
如需完整的範本參數清單,請參閱範本參數。
替代專案範本參數
在 SimpleProjectNode.cs 檔案中,移除
AddFileFromTemplate
方法。在 \Templates\Projects\ConsoleApp\SimpleProject.myproj 檔案中,找出 <RootNamespace> 屬性,並將其值變更為 $safeprojectname$。
<RootNamespace>$safeprojectname$</RootNamespace>
在 \Templates\Projects\SimpleProject\Program.cs 檔案中,以下列程式碼取代檔案的內容:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; // Guid namespace $safeprojectname$ { [Guid("$guid1$")] public class $safeprojectname$ { static void Main(string[] args) { Console.WriteLine("Hello VSX!!!"); Console.ReadKey(); } } }
重建 SimpleProject 專案並開始偵錯。 應該會出現實驗執行個體。
建立新的 SimpleProject 主控台應用程式。 (在 [專案類型] 窗格中,選取 [SimpleProject]。在 [Visual Studio 安裝的範本] 下,選取 [主控台應用程式]。)
在新建的專案中,開啟 Program.cs。 它看起來應該如下所示 (檔案中的 GUID 值會有所不同):
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; // Guid namespace Console_Application1 { [Guid("00000000-0000-0000-00000000-00000000)"] public class Console_Application1 { static void Main(string[] args) { Console.WriteLine("Hello VSX!!!"); Console.ReadKey(); } } }
建立專案屬性頁
您可以為專案類型建立屬性頁,讓使用者可以在以範本為基礎的專案中檢視和變更屬性。 本節說明如何建立與組態無關的屬性頁。 這個基本屬性頁會使用屬性方格來顯示您在屬性頁類別中公開的公用屬性。
從 SettingsPage
基底類別衍生屬性頁類別。 SettingsPage
類別所提供的屬性方格會知道大部分的基本資料型別,並知道如何顯示它們。 此外,SettingsPage
類別知道如何將屬性值保存到專案檔。
您在本節建立的屬性頁可讓您更改並儲存這些專案屬性:
AssemblyName
OutputType
RootNamespace。
在 SimpleProjectPackage.cs 檔案中,將這個
ProvideObject
屬性新增至SimpleProjectPackage
類別:[ProvideObject(typeof(GeneralPropertyPage))] public sealed class SimpleProjectPackage : ProjectPackage
這會向 COM 註冊屬性頁類別
GeneralPropertyPage
。在 SimpleProjectNode.cs 檔案中,將這兩個覆寫的方法新增至
SimpleProjectNode
類別:protected override Guid[] GetConfigurationIndependentPropertyPages() { Guid[] result = new Guid[1]; result[0] = typeof(GeneralPropertyPage).GUID; return result; } protected override Guid[] GetPriorityProjectDesignerPages() { Guid[] result = new Guid[1]; result[0] = typeof(GeneralPropertyPage).GUID; return result; }
這兩種方法都會傳回屬性頁 GUID 的陣列。 GeneralPropertyPage GUID 是陣列中唯一的元素,因此 [屬性頁] 對話方塊只會顯示一頁。
將名為 GeneralPropertyPage.cs 的類別檔案新增至 SimpleProject 專案。
使用下列程式碼來取代這個檔案的內容:
using System; using System.Runtime.InteropServices; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Project; using System.ComponentModel; namespace SimpleProject { [ComVisible(true)] [Guid("6BC7046B-B110-40d8-9F23-34263D8D2936")] public class GeneralPropertyPage : SettingsPage { private string assemblyName; private OutputType outputType; private string defaultNamespace; public GeneralPropertyPage() { this.Name = "General"; } [Category("AssemblyName")] [DisplayName("AssemblyName")] [Description("The output file holding assembly metadata.")] public string AssemblyName { get { return this.assemblyName; } } [Category("Application")] [DisplayName("OutputType")] [Description("The type of application to build.")] public OutputType OutputType { get { return this.outputType; } set { this.outputType = value; this.IsDirty = true; } } [Category("Application")] [DisplayName("DefaultNamespace")] [Description("Specifies the default namespace for added items.")] public string DefaultNamespace { get { return this.defaultNamespace; } set { this.defaultNamespace = value; this.IsDirty = true; } } protected override void BindProperties() { this.assemblyName = this.ProjectMgr.GetProjectProperty("AssemblyName", true); this.defaultNamespace = this.ProjectMgr.GetProjectProperty("RootNamespace", false); string outputType = this.ProjectMgr.GetProjectProperty("OutputType", false); this.outputType = (OutputType)Enum.Parse(typeof(OutputType), outputType); } protected override int ApplyChanges() { this.ProjectMgr.SetProjectProperty("AssemblyName", this.assemblyName); this.ProjectMgr.SetProjectProperty("OutputType", this.outputType.ToString()); this.ProjectMgr.SetProjectProperty("RootNamespace", this.defaultNamespace); this.IsDirty = false; return VSConstants.S_OK; } } }
GeneralPropertyPage
類別會公開三個公用屬性 AssemblyName、OutputType 和 RootNamespace。 因為 AssemblyName 沒有 set 方法,所以會顯示為唯讀屬性。 OutputType 是列舉常數,因此會顯示為下拉式清單。SettingsPage
基底類別提供ProjectMgr
來保存屬性。BindProperties
方法使用ProjectMgr
來擷取保存的屬性值,並設定相對應的屬性。ApplyChanges
方法使用ProjectMgr
來取得屬性的值,並將其保存至專案檔。 屬性集方法會將IsDirty
設定為 true,表示必須保存屬性。 儲存專案或方案時會持續保存。重建 SimpleProject 方案並開始偵錯。 應該會出現實驗執行個體。
在實驗執行個體中,建立新的 SimpleProject 應用程式。
Visual Studio 會呼叫您的專案處理站,以使用 Visual Studio 範本建立專案。 新的 Program.cs 檔案會在程式碼編輯器中開啟。
在 [方案總管] 中,以滑鼠右鍵按一下專案程式碼,然後按一下 [屬性]。 [屬性頁] 對話方塊隨即出現。
測試專案屬性頁
現在您可以測試是否可以修改和變更屬性值了。
在 [MyConsoleApplication 屬性頁] 對話方塊中,將 [DefaultNamespace] 變更為 [MyApplication]。
選取 [OutputType] 屬性,然後選取 [類別庫]。
按一下套用,再按一下確定。
重新開啟 [屬性頁] 對話方塊,並確認您的變更已保存。
關閉 Visual Studio 的實驗執行個體。
重新開啟實驗執行個體。
重新開啟 [屬性頁] 對話方塊,並確認您的變更已保存。
關閉 Visual Studio 的實驗執行個體。