共用方式為


建立基本的專案系統,第 1 部分

在 Visual Studio 中,專案是開發人員用來組織原始碼檔案和其他資產的容器。 專案會在方案總管中顯示為方案的子系。 專案可讓您組織、建置、偵錯及部署原始程式碼,以及建立 Web 服務、資料庫和其他資源的參考。

專案定義於專案檔中,例如 .csproj 檔案用於 Visual C# 專案。 您可以建立自己的專案類型,並具有專屬的專案副檔名。 如需專案類型的詳細資訊,請參閱專案類型

注意

如果您需要使用自訂專案類型來擴充 Visual Studio,強烈建議您利用 Visual Studio 專案系統 (VSPS),相較於從頭開始建置專案系統,這具有幾個優點:

  • 更容易上線。 即使是基本專案系統也需要數萬行程式碼。 利用 VSPS 可讓您在準備好根據需求進行自訂前,將上線成本減少為只需幾個按鍵。

  • 更容易維護。 利用 VSPS,您只需要維護自己的案例。 我們會處理所有專案系統基礎結構的維護工作。

    如果您需要以 Visual Studio 2013 之前的 Visual Studio 版本為目標,您將無法在 Visual Studio 延伸模組中運用 VSPS。 如果是這種情況,本逐步解說是開始著手的好地方。

本逐步解說說明如何建立專案副檔名 .myproj 的專案類型。 本逐步解說會借用現有的 Visual C# 專案系統。

注意

如需延伸模組專案的詳細資訊,請參閱 VSSDK 範例

本逐步解說教導如何完成以下任務:

  • 建立基本專案類型。

  • 建立基本專案範本。

  • 向 Visual Studio 註冊專案範本。

  • 開啟 [新增專案] 對話方塊,然後使用範本來建立專案執行個體

  • 為您的專案系統建立專案處理站。

  • 為您的專案系統建立專案節點。

  • 為專案系統新增自訂圖示。

  • 實作基本範本參數替代。

必要條件

下載適用於專案的 Managed Package Framework 原始程式碼。 將檔案解壓縮到您要建立之方案可存取的位置。

建立基本專案類型

建立名為 SimpleProject 的 C# VSIX 專案。 ([檔案]>[新增]>[專案],然後 [Visual C#]>[擴充性]>[VSIX 專案])。 新增 Visual Studio 套件專案項目範本 (在 [方案總管]上,以滑鼠右鍵按一下專案節點,並選取 [新增]>[新增項目],然後移至 [擴充性]>[Visual Studio 套件])。 將檔案命名為 SimpleProjectPackage

建立基本專案範本

現在,您可以修改這個基本 VSPackage 來實作新的 .myproj 專案類型。 若要建立以 .myproj 專案類型為基礎的專案,Visual Studio 必須知道要新增至新專案的檔案、資源和參考。 若要提供這項資訊,請將專案檔放在專案範本資料夾中。 當使用者使用 .myproj 專案建立專案時,會將檔案複製到新專案。

建立基本專案範本

  1. 將三個資料夾新增至專案,將一個放在另一個底下:Templates\Projects\SimpleProject。 (在 [方案總管]中,以滑鼠右鍵按一下 [SimpleProject] 專案節點,指向 [新增],然後按一下 [新增資料夾]。將資料夾命名為 Templates。在 [Templates] 資料夾中,新增名為 Projects 的資料夾。在 [Projects] 資料夾中,新增名為 SimpleProject 的資料夾。

  2. 在 Templates\Projects\SimpleProject 資料夾中,新增點陣圖影像檔案,用作為名為 SimpleProject.ico 的圖示。 當您按一下 [新增] 時,圖示編輯器隨即開啟。

  3. 讓圖示與眾不同。 本圖示會出現在逐步解說稍後的 [新增專案] 對話方塊中。

    Simple Project Icon

  4. 儲存圖示並關閉圖示編輯器。

  5. 在 Templates\Projects\SimpleProject 資料夾中,新增名為 Program.csClass 項目。

  6. 將現有的程式碼取代為下列幾行。

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace $nameSpace$
    {
        public class $className$
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello VSX!!!");
                Console.ReadKey();
            }
        }
    }
    

    重要

    這不是 Program.cs 程式碼的最終形式;取代參數會在稍後的步驟中處理。 您可能會看到編譯錯誤,但只要檔案的 BuildActionContent,您應該能夠如往常建置並執行專案。

  7. 儲存檔案。

  8. 將 AssemblyInfo.cs 檔案從 [Properties] 資料夾複製到 [Projects\SimpleProject] 資料夾。

  9. 在 [Projects\SimpleProject] 資料夾中,新增名為 SimpleProject.myproj 的 XML 檔案。

    注意

    所有此類專案的副檔名為 .myproj。 如果您想要變更它,必須在逐步解說中任何提及它的地方進行變更。

  10. 將現有內容取代為下列幾行。

    <?xml version="1.0" encoding="utf-8" ?>
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <SchemaVersion>2.0</SchemaVersion>
        <ProjectGuid></ProjectGuid>
        <OutputType>Exe</OutputType>
        <RootNamespace>MyRootNamespace</RootNamespace>
        <AssemblyName>MyAssemblyName</AssemblyName>
        <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
        <DebugSymbols>true</DebugSymbols>
        <OutputPath>bin\Debug\</OutputPath>
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
        <DebugSymbols>false</DebugSymbols>
        <OutputPath>bin\Release\</OutputPath>
      </PropertyGroup>
      <ItemGroup>
        <Reference Include="mscorlib" />
        <Reference Include="System" />
        <Reference Include="System.Data" />
        <Reference Include="System.Xml" />
      </ItemGroup>
      <ItemGroup>
        <Compile Include="AssemblyInfo.cs">
          <SubType>Code</SubType>
        </Compile>
        <Compile Include="Program.cs">
          <SubType>Code</SubType>
        </Compile>
      </ItemGroup>
      <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    </Project>
    
  11. 儲存檔案。

  12. 在 [屬性] 視窗中,將 AssemblyInfo.cs、Program.cs、SimpleProject.ico 和 SimpleProject.myproj 的 [建置動作] 設為 [內容],並將其 [包含在 VSIX 屬性] 中設定為 [True]

    此專案範本描述的是一個具有偵錯組態和發行組態的基本 Visual C# 專案。 專案包含兩個原始程式檔、AssemblyInfo.cs 和 Program.cs,以及數個組件參考。 從範本建立專案時,ProjectGuid 值會自動以新的 GUID 取代。

    在 [方案總管]中,展開的 [Templates] 資料夾應該如下所示:

Templates
   Projects
      SimpleProject
         AssemblyInfo.cs
         Program.cs
         SimpleProject.ico
         SimpleProject.myproj

建立基本專案處理站

您必須告訴 Visual Studio 專案範本資料夾的位置。 若要這麼做,請將屬性新增至實作專案處理站的 VSPackage 類別,以便在建置 VSPackage 時將範本位置寫入系統登錄。 首先,建立依專案處理站 GUID 識別的基本專案處理站。 使用 ProvideProjectFactoryAttribute 屬性將專案處理站連接到 SimpleProjectPackage 類別。

建立基本專案處理站

  1. 為您的專案處理站建立 GUID (在 [工具] 功能表上,按一下 [建立 GUID]),或使用下列範例中的 GUID。 將 GUID 新增至包含已定義 PackageGuidString 的區段附近的 SimpleProjectPackage 類別。 GUID 必須同時位於 GUID 表單和字串表單中。 產生的程式碼應該與下列範例類似。

        public sealed class SimpleProjectPackage : Package
        {
            ...
            public const string SimpleProjectPkgString = "96bf4c26-d94e-43bf-a56a-f8500b52bfad";
            public const string SimpleProjectFactoryString = "471EC4BB-E47E-4229-A789-D1F5F83B52D4";
    
            public static readonly Guid guidSimpleProjectFactory = new Guid(SimpleProjectFactoryString);
        }
    
  2. 將類別新增至名為 SimpleProjectFactory.cs 的最上層 [SimpleProject] 資料夾。

  3. 新增以下 using 指示詞:

    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Shell;
    
  4. 將 GUID 屬性新增至 SimpleProjectFactory 類別。 屬性的值是新的專案處理站 GUID。

    [Guid(SimpleProjectPackage.SimpleProjectFactoryString)]
    class SimpleProjectFactory
    {
    }
    

    您現在可以註冊專案範本了。

註冊專案範本

  1. 在 SimpleProjectPackage.cs 中,將 ProvideProjectFactoryAttribute 屬性新增至 SimpleProjectPackage 類別,如下所示。

    [ProvideProjectFactory(    typeof(SimpleProjectFactory),     "Simple Project",
        "Simple Project Files (*.myproj);*.myproj", "myproj", "myproj",
        @"Templates\Projects\SimpleProject",     LanguageVsTemplate = "SimpleProject")]
    [Guid(SimpleProjectPackage.PackageGuidString)]
    public sealed class SimpleProjectPackage : Package
    
  2. 重建方案並確認建置沒有發生錯誤。

    重建作業會註冊專案範本。

    參數 defaultProjectExtensionpossibleProjectExtensions 會設定為專案副檔名 (.myproj)。 projectTemplatesDirectory 參數會設定為 [Templates] 資料夾的相對路徑。 在建置期間,此路徑會轉換成完整組建,並新增至登錄以註冊專案系統。

測試範本註冊

範本註冊會向 Visual Studio 告知專案範本資料夾的位置,讓 Visual Studio 可以在 [新增專案] 對話方塊中顯示範本名稱和圖示。

測試範本註冊

  1. F5 開始對 Visual Studio 的實驗執行個體進行偵錯。

  2. 在實驗執行個體中,建立新建之專案類型的新專案。 在 [新增專案] 對話方塊中,您應該會在 [已安裝的範本] 底下看到 [SimpleProject]

    您現在有一個已註冊的專案處理站。 不過,它尚無法建立專案。 專案套件和專案處理站會共同運作,以建立和初始化專案。

新增 Managed Package Framework 程式碼

實作專案套件與專案處理站之間的連線。

  • 匯入 Managed Package Framework 的原始碼檔案。

    1. 卸載 SimpleProject 專案 (在 [方案總管]中,選取專案節點,然後在操作功能表上按一下 [卸載專案]。),並在 XML 編輯器中開啟專案檔。

    2. 將下列區塊新增至專案檔 (在 <Import> 區塊正上方)。 在您剛才下載的 Managed Package Framework 程式碼中,將 ProjectBasePath 設定為 ProjectBase.files 檔案的位置。 您可能需要在 pathname 加入反斜線。 如果不這麼做,專案可能找不到 Managed Package Framework 原始程式碼。

      <PropertyGroup>
           <ProjectBasePath>your path here\</ProjectBasePath>
           <RegisterWithCodebase>true</RegisterWithCodebase>
        </PropertyGroup>
        <Import Project="$(ProjectBasePath)\ProjectBase.Files" />
      

      重要

      別忘了路徑結尾的反斜線。

    3. 重新載入專案。

    4. 加入下列組件的參考:

      • Microsoft.VisualStudio.Designer.Interfaces (在 <VSSDK install>\VisualStudioIntegration\Common\Assemblies\v2.0 中)

      • WindowsBase

      • Microsoft.Build.Tasks.v4.0

初始化專案處理站

  1. 在 SimpleProjectPackage.cs 檔案中,新增下列 using 指示詞。

    using Microsoft.VisualStudio.Project;
    
  2. Microsoft.VisualStudio.Package.ProjectPackage 衍生 SimpleProjectPackage 類別。

    public sealed class SimpleProjectPackage : ProjectPackage
    
  3. 註冊專案處理站。 在 base.Initialize 之後的 SimpleProjectPackage.Initialize 方法中加入下列幾行:

    base.Initialize();
    this.RegisterProjectFactory(new SimpleProjectFactory(this));
    
  4. 實作抽象屬性 ProductUserContext

    public override string ProductUserContext
        {
            get { return ""; }
    }
    
  5. 在 SimpleProjectFactory.cs 中,於現有的 using 指示詞後面新增下列 using 指示詞。

    using Microsoft.VisualStudio.Project;
    
  6. ProjectFactory 衍生 SimpleProjectFactory 類別。

    class SimpleProjectFactory : ProjectFactory
    
  7. 將下列虛擬方法新增至 SimpleProjectFactory 類別。 您會在稍後的章節中實作這個方法。

    protected override ProjectNode CreateProject()
    {
        return null;
    }
    
  8. 將以下欄位和建構函式新增至 SimpleProjectFactory 類別。 此 SimpleProjectPackage 參考會快取在私人欄位中,以便用於設定服務提供者網站。

    private SimpleProjectPackage package;
    
    public SimpleProjectFactory(SimpleProjectPackage package)
        : base(package)
    {
        this.package = package;
    }
    
  9. 重建方案並確認建置沒有發生錯誤。

測試專案處理站實作

測試是否會呼叫專案處理站實作的建構函式。

測試專案處理站實作

  1. 在 SimpleProjectFactory.cs 檔案中,於 SimpleProjectFactory 建構函式的下列這一行上設定中斷點。

    this.package = package;
    
  2. F5 啟動 Visual Studio 的實驗執行個體。

  3. 在實驗執行個體中,開始建立新的專案。 在 [新增專案] 對話方塊中,選取 [SimpleProject] 專案類型,然後按一下 [確定]。 執行會在中斷點停止。

  4. 清除中斷點並停止偵錯。 因為我們尚未建立專案節點,因此專案建立程式碼仍然會擲回例外狀況。

擴充 ProjectNode 類別

現在您可以實作 SimpleProjectNode 類別,這是衍生自 ProjectNode 類別。 ProjectNode 基底類別會處理專案建立的下列工作:

  • 將專案範本檔案 SimpleProject.myproj 複製到新的專案資料夾。 複本會根據 [新增專案] 對話方塊中輸入的名稱重新命名。 ProjectGuid 屬性值會以新的 GUID 取代。

  • 周遊專案範本檔案 SimpleProject.myproj 的 MSBuild 元素,並尋找 Compile 元素。 針對每個 Compile 目標檔案,將檔案複製到新的專案資料夾。

    衍生的 SimpleProjectNode 類別會處理下列工作:

  • 在 [方案總管]中啟用要建立或選取之專案和檔案節點的圖示。

  • 允許指定其他專案範本參數替代。

擴充 ProjectNode 類別

  1. 新增名為 SimpleProjectNode.cs 的類別。

  2. 將現有的程式碼取代為下列程式碼。

    using System;
    using System.Collections.Generic;
    using Microsoft.VisualStudio.Project;
    
    namespace SimpleProject
    {
        public class SimpleProjectNode : ProjectNode
        {
            private SimpleProjectPackage package;
    
            public SimpleProjectNode(SimpleProjectPackage package)
            {
                this.package = package;
            }
            public override Guid ProjectGuid
            {
                get { return SimpleProjectPackage.guidSimpleProjectFactory; }
            }
            public override string ProjectType
            {
                get { return "SimpleProjectType"; }
            }
    
            public override void AddFileFromTemplate(
                string source, string target)
            {
                this.FileTemplateProcessor.UntokenFile(source, target);
                this.FileTemplateProcessor.Reset();
            }
        }
    }
    

    這個 SimpleProjectNode 類別實作具有這些覆寫的方法:

  • ProjectGuid,會傳回專案處理站 GUID。

  • ProjectType,會傳回專案型別的當地語系化名稱。

  • AddFileFromTemplate,會將選取的檔案從範本資料夾複製到目的地專案。 這個方法會在稍後的章節中進一步實作。

    SimpleProjectNode 建構函式就像 SimpleProjectFactory 建構函式一樣,會在私用欄位中快取 SimpleProjectPackage 參考以供稍後使用。

    若要將 SimpleProjectFactory 類別連接到 SimpleProjectNode 類別,您必須在 SimpleProjectFactory.CreateProject 方法中具現化新的 SimpleProjectNode,並將其快取在私用欄位中,以供稍後使用。

連接專案處理站類別和節點類別

  1. 在 SimpleProjectFactory.cs 檔案中,新增下列 using 指示詞。

    using IOleServiceProvider =    Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
    
  2. 使用下列程式碼取代 SimpleProjectFactory.CreateProject 方法。

    protected override ProjectNode CreateProject()
    {
        SimpleProjectNode project = new SimpleProjectNode(this.package);
    
        project.SetSite((IOleServiceProvider)        ((IServiceProvider)this.package).GetService(            typeof(IOleServiceProvider)));
        return project;
    }
    
  3. 重建方案並確認建置沒有發生錯誤。

測試 ProjectNode 類別

測試您的專案處理站,查看它是否建立專案階層。

測試 ProjectNode 類別

  1. F5 開始偵錯作業。 在實驗執行個體中,建立新的 SimpleProject。

  2. Visual Studio 應該會呼叫您的專案處理站來建立專案。

  3. 關閉 Visual Studio 的實驗執行個體。

新增自訂專案節點圖示

上一節中的專案節點圖示是預設圖示。 您可以將它變更為自訂圖示。

新增自訂專案節點圖示

  1. 在 [Resources] 資料夾中,新增名為 SimpleProjectNode.bmp 的點陣圖檔案。

  2. 在 [屬性] 視窗中,將點陣圖縮減為 16 x 16 像素。 讓點陣圖與眾不同。

    Simple Project Comm

  3. 在 [屬性] 視窗中,將點陣圖的 [建置動作] 變更為 [內嵌資源]

  4. 在 SimpleProjectNode.cs 中,新增下列 using 指示詞:

    using System.Drawing;
    using System.Windows.Forms;
    
  5. 將以下靜態欄位和建構函式新增至 SimpleProjectNode 類別。

    private static ImageList imageList;
    
    static SimpleProjectNode()
    {
        imageList =        Utilities.GetImageList(            typeof(SimpleProjectNode).Assembly.GetManifestResourceStream(                "SimpleProject.Resources.SimpleProjectNode.bmp"));
    }
    
  6. 將下列屬性加入到 SimpleProjectNode 類別的開頭。

    internal static int imageIndex;
       public override int ImageIndex
       {
           get { return imageIndex; }
       }
    
  7. 將執行個體建構函式取代為下列程式碼。

    public SimpleProjectNode(SimpleProjectPackage package)
    {
        this.package = package;
    
        imageIndex = this.ImageHandler.ImageList.Images.Count;
    
        foreach (Image img in imageList.Images)
        {
            this.ImageHandler.AddImage(img);
        }
    }
    

    在靜態建構期間,SimpleProjectNode 會從組件資訊清單資源擷取專案節點點陣圖,並快取在私人欄位中以供稍後使用。 請注意 GetManifestResourceStream 影像路徑的語法。 若要查看內嵌在組件中的資訊清單資源名稱,請使用 GetManifestResourceNames 方法。 當此方法套用至 SimpleProject 組件時,結果應該如下所示:

  • SimpleProject.Resources.resources

  • VisualStudio.Project.resources

  • SimpleProject.VSPackage.resources

  • Resources.imagelis.bmp

  • Microsoft.VisualStudio.Project.DontShowAgainDialog.resources

  • Microsoft.VisualStudio.Project.SecurityWarningDialog.resources

  • SimpleProject.Resources.SimpleProjectNode.bmp

    在執行個體建構期間,ProjectNode 基底類別會載入 Resources.imagelis.bmp,其中內嵌了來自 Resources\imagelis.bmp 的 16 x 16 點陣圖。 這個點陣圖清單會做為 ImageHandler.ImageListSimpleProjectNode 使用。 SimpleProjectNode 會將專案節點點陣圖附加至清單。 影像清單中的專案節點點陣圖位移會快取,以供稍後用作為公用 ImageIndex 屬性的值。 Visual Studio 會使用這個屬性來判斷要顯示為專案節點圖示的點陣圖。

測試自訂專案節點圖示

測試您的專案處理站,查看它是否建立具有自訂專案節點圖示的專案階層。

測試自訂專案節點圖示

  1. 開始偵錯,並在實驗執行個體中建立新的 SimpleProject。

  2. 在新建的專案中,請注意 SimpleProjectNode.bmp 用作為專案節點圖示。

    Simple Project New Project Node

  3. 在程式碼編輯器中開啟 Program.cs。 您應該會看到類似於以下程式碼的原始程式碼。

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace $nameSpace$
    {
        public class $className$
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello VSX!!!");
                Console.ReadKey();
            }
        }
    }
    

    請注意,範本參數 $nameSpace$ 和 $className$ 沒有新的值。 您將在下一節中學習如何實作範本參數替代。

替代範本參數

在先前的章節中,您使用了 ProvideProjectFactory 屬性向 Visual Studio 註冊專案範本。 以這種方式註冊範本資料夾的路徑,可讓您藉由覆寫和展開 ProjectNode.AddFileFromTemplate 類別來啟用基本範本參數替代。 如需詳細資訊,請參閱產生新專案:深入探討,第二部分

現在,將取代程式碼新增至 AddFileFromTemplate 類別。

替代範本參數

  1. 在 SimpleProjectNode.cs 檔案中,新增下列 using 指示詞。

    using System.IO;
    
  2. 使用下列程式碼取代 AddFileFromTemplate 方法。

    public override void AddFileFromTemplate(
        string source, string target)
    {
        string nameSpace =
            this.FileTemplateProcessor.GetFileNamespace(target, this);
        string className = Path.GetFileNameWithoutExtension(target);
    
        this.FileTemplateProcessor.AddReplace("$nameSpace$", nameSpace);
        this.FileTemplateProcessor.AddReplace("$className$", className);
    
        this.FileTemplateProcessor.UntokenFile(source, target);
        this.FileTemplateProcessor.Reset();
    }
    
  3. 在方法中設定中斷點,就在 className 指派陳述式之後。

    指派陳述式會決定命名空間和新類別名稱的合理值。 這兩個 ProjectNode.FileTemplateProcessor.AddReplace 方法呼叫會使用這些新值來取代相對應的範本參數值。

測試範本參數替代

現在您可以測試範本參數替代了。

測試範本參數替代

  1. 開始偵錯,並在實驗執行個體中建立新的 SimpleProject。

  2. AddFileFromTemplate 方法的中斷點執行停止。

  3. 檢查 nameSpaceclassName 參數的值。

    • \Templates\Projects\SimpleProject\SimpleProject.myproj 專案範本檔中 <RootNamespace> 元素的值會提供給 nameSpace。 此處的值為 MyRootNamespace

    • 類別來源檔名的值會提供給 className,不含副檔名。 在本例中,要複製到目的地資料夾的第一個檔案是 AssemblyInfo.cs,因此 className 的值是 AssemblyInfo

  4. 移除中斷點,並按 F5 以繼續執行。

    Visual Studio 應該會完成建立專案。

  5. 在程式碼編輯器中開啟 Program.cs。 您應該會看到類似於以下程式碼的原始程式碼。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MyRootNamespace
    {
        public class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello VSX!!!");
                Console.ReadKey();
            }
        }
    }
    

    請注意,命名空間現在是 MyRootNamespace,而類別名稱現在是 Program

  6. 開始對專案進行偵錯。 新專案應該在貯控台視窗中編譯、執行及顯示「Hello VSX!!!」。

    Simple Project Command

    恭喜! 您已實作基本的受控專案系統。