使用 MSBuild 建立 NuGet 套件Create a NuGet package using MSBuild

當您從程式碼建立 NuGet 套件時,會將該功能封裝至可由任意數目的其他開發人員共用和使用的元件。When you create a NuGet package from your code, you package that functionality into a component that can be shared with and used by any number of other developers. 本文說明如何使用 MSBuild 建立套件。This article describes how to create a package using MSBuild. MSBuild 會使用每個包含 NuGet 的 Visual Studio 工作負載來進行預先安裝。MSBuild comes preinstalled with every Visual Studio workload that contains NuGet. 此外,您也可以透過 dotnet CLI 搭配dotnet msbuild使用 msbuild。Additionally you can also use MSBuild through the dotnet CLI with dotnet msbuild.

針對使用 SDK 樣式格式與任何其他 SDK 樣式專案的 .NET Core 與 .NET Standard 專案,NuGet 會直接使用專案檔中的資訊來建立套件。For .NET Core and .NET Standard projects that use the SDK-style format, and any other SDK-style projects, NuGet uses information in the project file directly to create a package. 針對使用 <PackageReference> 的非 SDK 樣式專案,NuGet 也會使用專案檔來建立套件。For a non-SDK-style project that uses <PackageReference>, NuGet also uses the project file to create a package.

SDK 樣式的專案預設會提供套件功能。SDK-style projects have the pack functionality available by default. 針對非 SDK 樣式的 PackageReference 專案,您必須將 NuGet.Build.Tasks.Pack 套件新增至專案相依性。For non SDK-style PackageReference projects, you need to add the NuGet.Build.Tasks.Pack package to the project dependencies. 如需 MSBuild 套件目標的詳細資訊,請參閱 NuGet 套件和還原為 MSBuild 目標For detailed information about MSBuild pack targets, see NuGet pack and restore as MSBuild targets.

建立套件的命令 msbuild -t:pack 是相當於 dotnet pack 的功能。The command that creates a package, msbuild -t:pack, is functionality equivalent to dotnet pack.

重要

本主題適用於 SDK 樣式的專案 (通常是 .NET Core 和 .NET Standard 專案),以及適用於使用 PackageReference 的非 SDK 樣式專案。This topic applies to SDK-style projects, typically .NET Core and .NET Standard projects, and to non-SDK-style projects that use PackageReference.

設定屬性Set properties

建立套件時需要下列屬性。The following properties are required to create a package.

  • PackageId,套件識別碼,這在裝載套件的資源庫內必須是唯一的。PackageId, the package identifier, which must be unique across the gallery that hosts the package. 若未指定,則預設值為 AssemblyNameIf not specified, the default value is AssemblyName.
  • VersionMajor.Minor.Patch[-Suffix] 形式的特定版本號碼,其中 -Suffix 識別發行前版本Version, a specific version number in the form Major.Minor.Patch[-Suffix] where -Suffix identifies pre-release versions. 若未指定,則預設值為 1.0.0。If not specified, the default value is 1.0.0.
  • 主機上應該會出現套件標題 (例如 nuget.org)The package title as it should appear on the host (like nuget.org)
  • Authors,作者與擁有者資訊。Authors, author and owner information. 若未指定,則預設值為 AssemblyNameIf not specified, the default value is AssemblyName.
  • Company,您的公司名稱。Company, your company name. 若未指定,則預設值為 AssemblyNameIf not specified, the default value is AssemblyName.

此外,如果您要封裝使用 PackageReference 的非 SDK 樣式專案,則需要下列各項:Additionally if you are packing non-SDK-style projects that use PackageReference, the following is required:

  • PackageOutputPath,這是呼叫 pack 時所產生之封裝的輸出檔案夾。PackageOutputPath, the output folder for the package generated when calling pack.

在 Visual Studio 中,您可以在專案屬性中設定這些值 (在 [方案總管] 中以滑鼠右鍵按一下專案,選擇 [屬性],然後選取 [套件] 索引標籤)。In Visual Studio, you can set these values in the project properties (right-click the project in Solution Explorer, choose Properties, and select the Package tab). 您也可以直接在專案檔 (.csproj) 中設定這些屬性。You can also set these properties directly in the project files (.csproj).

<PropertyGroup>
  <PackageId>ClassLibDotNetStandard</PackageId>
  <Version>1.0.0</Version>
  <Authors>your_name</Authors>
  <Company>your_company</Company>
</PropertyGroup>

重要

為套件指定識別碼,此識別碼在 nuget.org 上或您使用的任何套件資源上都必須是唯一的。Give the package an identifier that's unique across nuget.org or whatever package source you're using.

下列範例顯示一個簡單且完整的專案檔,其中會包含這些屬性The following example shows a simple, complete project file with these properties included.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <PackageId>ClassLibDotNetStandard</PackageId>
    <Version>1.0.0</Version>
    <Authors>your_name</Authors>
    <Company>your_company</Company>
  </PropertyGroup>
</Project>

您還可以設定選擇性屬性,例如TitlePackageDescriptionPackageTags,如 MSBuild 套件目標控制相依性資產,以及 NuGet 中繼資料屬性中所述。You can also set the optional properties, such as Title, PackageDescription, and PackageTags, as described in MSBuild pack targets, Controlling dependency assets, and NuGet metadata properties.

注意

針對公眾取用而建置的套件,請特別注意 PackageTags 屬性,因為標籤可協助其他人找到您的套件,並了解其用途。For packages built for public consumption, pay special attention to the PackageTags property, as tags help others find your package and understand what it does.

如需宣告相依性及指定版本號碼的詳細資料,請參閱專案檔中的套件參考套件版本控制For details on declaring dependencies and specifying version numbers, see Package references in project files and Package versioning. 使用 <IncludeAssets><ExcludeAssets> 屬性,也可以將來自相依性的資產直接用於套件中。It is also possible to surface assets from dependencies directly in the package by using the <IncludeAssets> and <ExcludeAssets> attributes. 如需詳細資訊,請參閱控制相依性資產For more information, seee Controlling dependency assets.

新增選擇性的描述欄位Add an optional description field

套件的選擇性描述(顯示在封裝的 [NuGet.org] 頁面上)會從 .csproj 檔案中使用的 <description></description> 提取,或透過nuspec檔案中的 $description 提取。The package's optional description, displayed on the package's NuGet.org page, is either pulled in from the <description></description> used in the .csproj file or pulled in via the $description in the .nuspec file.

[描述] 欄位的範例會顯示在 .net 封裝之 .csproj 檔案的下列 XML 文字中:An example of a description field is shown in the following XML text of the .csproj file for a .NET package:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <PackageId>Azure.Storage.Blobs</PackageId>
    <Version>12.4.0</Version>
    <PackageTags>Microsoft Azure Storage Blobs;Microsoft;Azure;Blobs;Blob;Storage;StorageScalable</PackageTags>
    <Description>
      This client library enables working with the Microsoft Azure Storage Blob service for storing binary and text data.
      For this release see notes - https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/README.md and https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md
      in addition to the breaking changes https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/BreakingChanges.txt
      Microsoft Azure Storage quickstarts and tutorials - https://docs.microsoft.com/en-us/azure/storage/
      Microsoft Azure Storage REST API Reference - https://docs.microsoft.com/en-us/rest/api/storageservices/
      REST API Reference for Blob Service - https://docs.microsoft.com/en-us/rest/api/storageservices/blob-service-rest-api
    </Description>
  </PropertyGroup>
</PropertyGroup>

選擇唯一的套件識別碼並設定版本號碼Choose a unique package identifier and set the version number

套件識別碼與版本號碼是專案中的兩個最重要值,因為它們可以唯一識別套件中所含的確切程式碼。The package identifier and the version number are the two most important values in the project because they uniquely identify the exact code that's contained in the package.

套件識別碼的最佳做法:Best practices for the package identifier:

  • 唯一性:在 nuget.org 內,或只要資源庫裝載套件時,識別碼就必須是唯一的。Uniqueness: The identifier must be unique across nuget.org or whatever gallery hosts the package. 決定識別碼之前,請搜尋適用的資源庫,檢查是否已在使用名稱。Before deciding on an identifier, search the applicable gallery to check if the name is already in use. 若要避免衝突,不錯的模式是使用您的公司名稱作為識別碼的第一個部分,例如 Contoso.To avoid conflicts, a good pattern is to use your company name as the first part of the identifier, such as Contoso..
  • 命名空間類似名稱:遵循與 .NET 中命名空間類似的模式,即使用點標記法,而非連字號。Namespace-like names: Follow a pattern similar to namespaces in .NET, using dot notation instead of hyphens. 例如,使用 Contoso.Utility.UsefulStuff,而非 Contoso-Utility-UsefulStuffContoso_Utility_UsefulStuffFor example, use Contoso.Utility.UsefulStuff rather than Contoso-Utility-UsefulStuff or Contoso_Utility_UsefulStuff. 套件識別碼符合程式碼中所使用的命名空間時,取用者也會發現它十分有用。Consumers also find it helpful when the package identifier matches the namespaces used in the code.
  • 範例套件:如果您產生的範例程式碼套件示範如何使用另一個套件,請將 .Sample 附加為識別碼的尾碼,如 Contoso.Utility.UsefulStuff.Sample 所示Sample Packages: If you produce a package of sample code that demonstrates how to use another package, attach .Sample as a suffix to the identifier, as in Contoso.Utility.UsefulStuff.Sample. (範例封裝當然會相依于另一個套件)。建立範例封裝時,請使用 <IncludeAssets>中的 contentFiles 值。(The sample package would of course have a dependency on the other package.) When creating a sample package, use the contentFiles value in <IncludeAssets>. content 資料夾中,於稱為 \Samples\<identifier> 的資料夾中排列範例程式碼,而這與 \Samples\Contoso.Utility.UsefulStuff.Sample 中相同。In the content folder, arrange the sample code in a folder called \Samples\<identifier> as in \Samples\Contoso.Utility.UsefulStuff.Sample.

套件版本的最佳做法:Best practices for the package version:

  • 一般而言,請設定套件版本,使其符合專案 (或組件),但這不是絕對必要。In general, set the version of the package to match the project (or assembly), though this is not strictly required. 當您將套件限制為單一組件時,這很簡單。This is a simple matter when you limit a package to a single assembly. 整體來說,請記住,解析相依性時,NuGet 本身會處理套件版本,而非組件版本。Overall, remember that NuGet itself deals with package versions when resolving dependencies, not assembly versions.
  • 使用非標準版本方式時,請務必考慮使用 NuGet 版本控制規則,如套件版本控制中所述。When using a non-standard version scheme, be sure to consider the NuGet versioning rules as explained in Package versioning. NuGet 大多符合 semver 2 規範NuGet is mostly semver 2 compliant.

如需相依性解析的相關資訊,請參閱使用 PackageReference 的相依性解析For information on dependency resolution, see Dependency resolution with PackageReference. 如需更深入了解版本控制的較舊資訊,請參閱這一系列的部落格文章。For older information that may also be helpful to better understand versioning, see this series of blog posts.

新增 NuGet.Build.Tasks.Pack 套件Add the NuGet.Build.Tasks.Pack package

如果您使用 MSBuild 搭配非 SDK 樣式的專案和 PackageReference,請將 NuGet.Build.Tasks.Pack 套件新增至您的專案。If you are using MSBuild with a non-SDK-style project and PackageReference, add the NuGet.Build.Tasks.Pack package to your project.

  1. 開啟專案檔,並在 <PropertyGroup> 元素之後新增下列內容:Open the project file and add the following after the <PropertyGroup> element:

    <ItemGroup>
      <!-- ... -->
      <PackageReference Include="NuGet.Build.Tasks.Pack" Version="5.2.0"/>
      <!-- ... -->
    </ItemGroup>
    
  2. 開啟開發人員命令提示字元 (在 [搜尋] 方塊中,輸入開發人員命令提示字元)。Open a Developer command prompt (In the Search box, type Developer command prompt).

    您通常想要從 [開始] 功能表啟動適用於 Visual Studio 的開發人員命令提示字元,因為它將使用適用於 MSBuild 的所有必要路徑來設定。You typically want to start the Developer Command Prompt for Visual Studio from the Start menu, as it will be configured with all the necessary paths for MSBuild.

  3. 切換至包含專案檔的資料夾,並輸入下列命令以安裝 NuGet.Build.Tasks.Pack 套件。Switch to the folder containing the project file and type the following command to install the NuGet.Build.Tasks.Pack package.

    # Uses the project file in the current folder by default
    msbuild -t:restore
    

    確定 MSBuild 輸出會指出組建已順利完成。Make sure that the MSBuild output indicates that the build completed successfully.

執行 msbuild -t:pack 命令Run the msbuild -t:pack command

若要從專案建置 NuGet 套件 (.nupkg 檔案),請執行 msbuild -t:pack 命令,該命令也會自動建置專案:To build a NuGet package (a .nupkg file) from the project, run the msbuild -t:pack command, which also builds the project automatically:

在 Visual Studio 開發人員命令提示字元中,輸入下列命令:In the Developer command prompt for Visual Studio, type the following command:

# Uses the project file in the current folder by default
msbuild -t:pack

輸出將顯示 .nupkg 檔案的路徑。The output shows the path to the .nupkg file.

Microsoft (R) Build Engine version 16.1.76+g14b0a930a7 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 8/5/2019 3:09:15 PM.
Project "C:\Users\username\source\repos\ClassLib_DotNetStandard\ClassLib_DotNetStandard.csproj" on node 1 (pack target(s)).
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
  ...
CopyFilesToOutputDirectory:
  Copying file from "C:\Users\username\source\repos\ClassLib_DotNetStandard\obj\Debug\netstandard2.0\ClassLib_DotNetStandard.dll" to "C:\Use
  rs\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.dll".
  ClassLib_DotNetStandard -> C:\Users\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.dll
  Copying file from "C:\Users\username\source\repos\ClassLib_DotNetStandard\obj\Debug\netstandard2.0\ClassLib_DotNetStandard.pdb" to "C:\Use
  rs\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.pdb".
GenerateNuspec:
  Successfully created package 'C:\Users\username\source\repos\ClassLib_DotNetStandard\bin\Debug\AppLogger.1.0.0.nupkg'.
Done Building Project "C:\Users\username\source\repos\ClassLib_DotNetStandard\ClassLib_DotNetStandard.csproj" (pack target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.21

建置時自動產生套件Automatically generate package on build

若要在您建置或還原專案時自動執行 msbuild -t:pack,請將下一行新增至專案檔的 <PropertyGroup> 中:To automatically run msbuild -t:pack when you build or restore the project, add the following line to your project file within <PropertyGroup>:

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

當您在解決方案上執行 msbuild -t:pack 時,這會封裝解決方案中可封裝的所有專案 ( 屬性會設定為 true)。When you run msbuild -t:pack on a solution, this packs all the projects in the solution that are packable ( property is set to true).

注意

當您自動產生套件時,封裝的時間會增加專案的建置時間。When you automatically generate the package, the time to pack increases the build time for your project.

測試套件安裝Test package installation

發行套件之前,您通常會想要測試將套件安裝至專案的程序。Before publishing a package, you typically want to test the process of installing a package into a project. 測試可確定必要檔案最後都在專案的正確位置。The tests make sure that the necessarily files all end up in their correct places in the project.

您可以使用一般套件安裝步驟,以在 Visual Studio 中或命令列上手動測試安裝。You can test installations manually in Visual Studio or on the command line using the normal package installation steps.

重要

套件是不可變的。Packages are immutable. 如果您更正了問題,請變更套件的內容並再次封裝,當您重新測試時,仍會使用舊版套件,直到您清除全域套件資料夾為止。If you correct a problem, change the contents of the package and pack again, when you retest you will still be using the old version of the package until you clear your global packages folder. 在測試每個組建上未使用唯一發行前版本標籤的套件時,這關係重大。This is especially relevant when testing packages that don't use a unique prerelease label on every build.

後續步驟Next Steps

建立套件 (即 .nupkg 檔案) 之後,即可將它發行至您選擇的資源庫,如發行套件中所述。Once you've created a package, which is a .nupkg file, you can publish it to the gallery of your choice as described on Publishing a Package.

您也可能想要擴充您套件的功能,或支援其他案例,如下列各主題中所述:You might also want to extend the capabilities of your package or otherwise support other scenarios as described in the following topics:

最後,請注意其他套件類型:Finally, there are additional package types to be aware of: