无论包的作用是什么或它包含的代码,都可以使用命令行接口(CLI)工具 nuget.exe 之一,或者 dotnet.exe将该功能打包到可以与其他开发人员共享和使用的组件中。 若要安装 NuGet CLI 工具,请参阅 安装 NuGet 客户端工具。 Visual Studio不会自动包含 CLI 工具。
对于通常.NET框架项目的非 SDK 样式项目,请按照本文中所述的步骤创建包。 有关 Visual Studio 和
nuget.exeCLI 的逐步操作指南,请参阅 快速入门:使用 Visual Studio(.NET Framework,Windows)创建和发布包。有关使用 SDK 样式格式的 .NET Core 和 .NET Standard 项目,以及其他任何 SDK 样式项目,请参阅 使用 dotnet CLI 创建 NuGet 包。
对于从
packages.config中PackageReference迁移到的项目,请使用msbuild -t:pack命令。
从技术上说,NuGet 包是一个 ZIP 文件,已重命名为扩展名 .nupkg ,其内容与某些约定匹配。 本文介绍创建满足这些约定的包的详细过程。
打包以编译的代码(程序集)、符号和其他要作为包传递的文件开头。 有关打包过程的概述,请参阅 包创建工作流。 此过程与编译或生成进入包的文件无关。 但是,可以从项目文件中的信息进行绘制,使编译的程序集和包保持同步。
重要
本文适用于非 SDK 样式项目,通常是使用 Visual Studio 2017 及更高版本和 NuGet 4.0+ .NET Core 和 .NET Standard 项目以外的项目。
确定要打包的程序集
大多数常规用途包包含一个或多个程序集,其他开发人员可以在自己的项目中使用这些程序集。
一般情况下,最好为每个 NuGet 包创建一个程序集,前提是每个程序集独立有用。 例如,请考虑以下涉及一个名为 Utilities.dll 的程序集,该程序集依赖于名为 Parser.dll的程序集:
如果 Parser.dll 本身很有用,请为 Utilities.dll 创建一个包,一个用于 Parser.dll。 这样,开发人员就可以独立于 Utilities.dll 使用 Parser.dll。
如果 Parser.dll 包含仅由 Utilities.dll使用的代码,那么可以在同一包中保留 Parser.dll。 通常,如果库由多个不独立有用的程序集组成,则最好将它们合并到一个包中。
如果 Utilities.dll 还依赖于 Utilities.resources.dll,并且 Utilities.resources.dll 本身没有用处,请将两者放在同一个包中。
资源(如前面的示例中 的Utilities.resources.dll 程序集)是一种特殊情况。 安装包到项目中时,NuGet 会自动将程序集引用添加到包的 DLL,但不包括 命名为 .resources.dll 的 DLL,因为这些 DLL 被假定为本地化的卫星程序集。 有关库的本地化版本的详细信息,请参阅 创建本地化的 NuGet 包。 因此,请避免对包含基本包代码的文件使用 .resources.dll 。
如果库包含组件对象模型 (COM) 互操作程序集,请遵循 “创建包含 COM 互操作程序集的 NuGet 包”中的其他准则。
.nuspec 文件的角色和结构
了解要打包的文件时,下一步是在 .nuspec XML 文件中创建包清单。
清单:
- 描述包的内容,并包含在包中。
- 驱动包的创建,并告知 NuGet 如何将包安装到项目中。 例如,清单标识其他包依赖项,以便 NuGet 也可以在安装主包时安装这些依赖项。
- 包含本节其余部分中所述的必需属性和可选属性。 有关详细信息,包括此处未提及的其他属性,请参阅 .nuspec 参考。
清单中需要以下属性:
- 包标识符,该标识符在承载包的库中必须唯一
- Major.Minor.Patch[-Suffix] 中的特定版本号,其中 -Suffix 标识预发行版本
- 程序包标题,因为它应出现在主机上(如 nuget.org)
- 作者信息
- 包裹的详细描述
以下属性是常见的可选属性:
- 发行说明。
- 版权信息。
- 在 Visual Studio 中的程序包管理器 UI的简短说明。
- 区域设置 ID。
- 项目网址。
- 以表达式或文件形式的许可证。 该
licenseUrl属性已弃用。 请改用licensenuspec 元数据元素 。 - 一个说明文件。
- 图标文件。 该
iconUrl属性已弃用。 请改用iconnuspec 元数据元素 。 - 依赖项和引用的列表。
- 有助于图库搜索的标记。
以下代码是典型的 (但虚构) .nuspec 文件,其中包含描述属性的注释:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<!-- An identifier that must be unique within the hosting gallery -->
<id>Contoso.Utility.UsefulStuff</id>
<!-- A package version number that's used when resolving dependencies -->
<version>1.8.3</version>
<!-- A comma-separated list of package authors that sometimes appears directly on the gallery -->
<authors>Dejana Tesic, Rajeev Dey</authors>
<!-- A project URL that provides a link for the gallery -->
<projectUrl>http://github.com/contoso/UsefulStuff</projectUrl>
<!-- License information that's displayed on the gallery -->
<license type="expression">Apache-2.0</license>
<!-- The location of a read-me file that's displayed in the Visual Studio Package Manager UI -->
<readme>readme.md</readme>
<!-- An icon that's used in the Visual Studio Package Manager UI -->
<icon>icon.png</icon>
<!--
A property that when true, prompts the user to accept the license when
installing the package
-->
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<!-- Detailed information about a particular release -->
<releaseNotes>Bug fixes and performance improvements</releaseNotes>
<!--
A description that can be used in the Package Manager UI. The
nuget.org gallery uses information you add in the portal.
-->
<description>Core utility functions for web applications</description>
<!-- Copyright information -->
<copyright>Copyright ©2026 Contoso Corporation</copyright>
<!-- Tags that appear in the gallery and can be used for tag searches -->
<tags>web utility http json url parsing</tags>
<!-- Dependencies that are automatically installed when the package is installed -->
<dependencies>
<dependency id="Newtonsoft.Json" version="9.0" />
</dependencies>
</metadata>
<!-- A read-me Markdown file that's displayed in the Package Manager UI -->
<files>
<file src="readme.md" target="" />
<file src="icon.png" target="" />
</files>
</package>
有关声明依赖项和指定版本号的详细信息,请参阅 packages.config 和 包版本控制。 还可以在dependency元素上使用include和exclude属性,来指定要在包中包含或排除的依赖项资产。 有关详细信息,请参阅 .nuspec Reference - Dependencies 元素。
由于清单包含在从中创建的包中,因此可以通过检查现有包来查找示例。 良好的源是计算机上的 全局包 文件夹。 若要查找其位置,请使用以下命令:
nuget locals -list global-packages
了解 全局包 文件夹的位置后,请执行以下步骤来查找清单文件:
- 转到 全局包 文件夹。
- 在该文件夹中,转到任何包的子文件夹,然后转到该包的任何版本的子文件夹。
- 在版本子文件夹中,创建 .nupkg 文件的副本,并将副本的扩展名更改为 zip。
- 打开 .zip 文件并检查其中 .nuspec 文件。
注释
从Visual Studio项目创建 .nuspec 文件时,清单中包含的一些标记会在生成包时替换为项目中的信息。 有关详细信息,请参阅 从 Visual Studio 项目创建 .nuspec 文件。
创建 .nuspec 文件
创建完整清单通常以通过以下方法之一生成的基本 .nuspec 文件开始:
然后手动编辑文件,以便描述最终包中所需的确切内容。
重要
使用 nuget pack 命令创建包之前,您必须修改生成的 .nuspec 文件中包含的占位符。 如果 .nuspec 文件包含任何占位符,该命令将失败。
从基于约定的工作目录
由于 NuGet 包是使用 .nupkg 扩展名重命名的 ZIP 文件,因此通常最容易在本地文件系统上创建所需的文件夹结构,然后直接从该结构创建 .nuspec 文件。 然后,该 nuget pack 命令会自动添加该文件夹结构中的所有文件,但它排除以句点开头的任何文件夹,以便可以将专用文件保留在同一结构中。
此方法的优点是,无需在清单中指定要包含在包中的文件,如本部分后面所述。 相反,你可以让生成过程生成进入包的确切文件夹结构。 还可以轻松包含可能不属于项目的其他文件,否则:
- 应注入目标项目的内容和源代码
- PowerShell 脚本
- 对项目中现有配置和源代码文件的转换
这些文件夹符合以下约定:
| 文件夹 | 内容 | 安装包时执行的操作 |
|---|---|---|
| (根) | 顶级文件夹、包清单,以及(可选的)README.md 文件和图标图像 | 此文件夹用作标准化子文件夹(如 lib 和 build)的起点。 |
| lib/<tfm> | 给定目标框架标识符(TFM)的程序集文件(.dll)、文档文件(.xml)和符号文件(.pdb) | 程序集被添加为在编译时和运行时使用的引用。 .xml 和 .pdb 文件将复制到项目文件夹中。 有关创建特定框架目标的子文件夹的信息,请参阅支持多个 .NET 版本。 |
| ref/<tfm> | 给定 TFM 的程序集文件(.dll)和符号文件(.pdb) | 程序集仅在编译时作为引用添加。 项目 bin 文件夹中未复制任何内容。 |
| 运行时 | 特定于体系结构的程序集(.dll)、符号(.pdb)和本机资源(.pri)文件 | 程序集仅作为引用在运行时添加。 其他文件将复制到项目文件夹中。 在/ref/<tfm> 文件夹下,应始终有一个对应 (TFM) AnyCPU 特定程序集,以提供相应的编译时程序集。 请参阅 支持多个 .NET 版本。 |
| 内容 | 任意文件 | 内容将复制到项目根目录。 将 内容 文件夹视为最终使用包的目标应用程序的根目录。 若要让包在应用程序的 /images 文件夹中添加图像,请将它放在包 的内容/图像 文件夹中。 |
| 构建 | (3.x+) Microsoft Build引擎(MSBuild).targets和.props文件 | 这些文件会自动插入到项目中。 |
| buildMultiTargeting | (4.0+) 用于跨框架目标的 MSBuild .targets 和 .props 文件 | 这些文件会自动插入到项目中。 |
| buildTransitive | (5.0+) MSBuild .targets 和 .props 文件,这些文件可传递流向任何使用的项目 | 这些文件会自动插入到项目中。 请参阅 功能 页。 |
| 工具 | 可从 程序包管理器 控制台访问的 PowerShell 脚本和程序 |
tools 文件夹仅添加到 程序包管理器 控制台的 PATH 环境变量中。 它 不会 添加到 MSBuild PATH 构建项目时使用的值中。 |
由于文件夹结构可以包含许多目标框架的程序集,因此在创建支持多个框架的包时,此方法是必需的。
准备好所需的文件夹结构后,在该文件夹中运行以下命令以创建 .nuspec 文件:
nuget spec
生成的 .nuspec 文件不包含对文件夹结构中的文件的显式引用。 NuGet 在创建包时自动包括所有文件。 你仍然需要编辑清单其他部分中的占位符值。
从程序集 DLL
在从程序集创建包的基本情况下,可以使用以下命令从程序集中的元数据生成 .nuspec 文件:
nuget spec <assembly-name>.dll
使用此表单将清单中的几个占位符替换为程序集中的特定值。 例如,该 <id> 属性设置为程序集名称,并 <version> 设置为程序集版本。 但是,清单中的其他属性在程序集中没有匹配的值。 运行命令后,这些属性仍然包含占位符。
从 Visual Studio 项目中
从 .csproj 或 .vbproj 文件创建 .nuspec 文件很方便,因为项目中安装的其他包会自动引用为依赖项。 若要从项目文件创建清单,请在包含项目文件的文件夹中使用以下命令:
# Use in a folder that contains a project file, such as <project-name>.csproj or <project-name>.vbproj.
nuget spec
生成的 <project-name.nuspec> 文件包含标记,这些 令牌 会在打包时用项目中的相应值替换,其中包括对已安装的任何其他包的引用。
如果包依赖项要包含在 .nuspec 中,请改用 nuget pack。 然后从生成的 .nupkg 文件中获取 .nuspec 文件。 例如,使用以下命令:
# Use in a folder that contains a project file, such as <project-name>.csproj or <project-name>.vbproj.
nuget pack myproject.csproj
标记由 $ 项目属性两侧的符号分隔。 例如, <id> 以这种方式生成的清单中的值通常类似于以下行:
<id>$id$</id>
此令牌将在打包时被项目文件中的 AssemblyName 值替换。 有关将项目值精确映射到 .nuspec 文件令牌的信息,请参阅 替换令牌。
使用令牌可避免在更新项目时需要手动更新关键值(例如 .nuspec 文件中的版本号)。 但你也可以将标记替换为文本值。
从Visual Studio项目中工作时,可以使用几种额外的打包选项,如本文后面所述的 运行 nuget pack 以生成 .nupkg 文件。
解决方案级包
仅 NuGet 2.x。 NuGet 3.0+ 中不可用。
NuGet 2.x 支持解决方案级包的概念,该包为 程序包管理器 控制台(tools 文件夹的内容)安装工具或额外命令,但不向解决方案中的任何项目添加引用、内容或生成自定义项。 此类包在其直接 库、 内容或 生成 文件夹中不包含文件,并且其依赖项中没有文件在其各自的 库、 内容或 生成 文件夹中。
NuGet 跟踪 .nuget 文件夹中 packages.config 文件中已安装的解决方案级包,而不是项目的 packages.config 文件。
从具有默认值的新文件开始
以下命令创建包含占位符的默认清单,这有助于确保从正确的文件结构开始:
nuget spec [<package-name>]
如果省略 <package-name>,生成的文件名为 Package.nuspec。 如果您提供诸如 Contoso.Utility.UsefulStuff 这样的名称,那么文件名将为 Contoso.Utility.UsefulStuff.nuspec。
生成的 .nuspec 文件包含类似于 projectUrl 的值的占位符。 在使用该文件创建最终的 .nupkg 文件之前,请将占位符替换为适当的值。
选择唯一的包标识符并设置版本号
包标识符(<id> 元素)和版本号(<version> 元素)是清单中最重要的两个值,因为它们唯一标识包中包含的确切代码。
包标识符的最佳做法
-
唯一性:标识符在承载包的库中必须是唯一的,例如 nuget.org。在决定标识符之前,请搜索适用的库,检查名称是否已在使用。 为了避免冲突,良好的模式是使用公司名称作为标识符的第一部分,例如
Contoso。 -
名称类似Namespace 的名称:遵循类似于.NET命名空间的模式,使用点表示法而不是连字符。 例如,使用
Contoso.Utility.UsefulStuff而不是Contoso-Utility-UsefulStuff或Contoso_Utility_UsefulStuff。 当包标识符与代码中使用的命名空间匹配时,使用者也会发现它很有用。 -
示例包:如果生成示例代码包,演示如何使用另一个包,请附加
.Sample为标识符的后缀,如中所示Contoso.Utility.UsefulStuff.Sample。 此类型的示例包依赖于它演示如何使用的包。 创建示例包时,请使用前面所述的基于约定的工作目录方法。 在内容文件夹中,按照 < 中所示,在名为 \Samples\>identifier 的文件夹中排列示例代码。
包版本的最佳做法
- 通常,将包的版本设置为与库匹配。 建议使用本指南,但并非严格要求。 将包限制为单个程序集时,这种做法非常简单,如前面在 决定要打包的程序集中所述。 通常,请记住,NuGet 本身在解析依赖项时处理包版本,而不是程序集版本。
- 使用非标准版本方案时,请考虑 包版本控制中所述的 NuGet 版本控制规则。
有关有助于了解版本控制的其他资源,请参阅以下一系列简短博客文章:
添加自述文件和其他文件
若要直接指定要包含在包中的文件,请使用 <files>.nuspec 文件中的节点,该文件遵循<metadata>标记:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<!-- ... -->
</metadata>
<files>
<!-- Add files from an arbitrary folder that's not necessarily in the project. -->
<file src="..\..\SomeRoot\**\*.*" target="" />
</files>
</package>
小窍门
使用基于约定的工作目录方法时,可以将 readme.md 文件放在包根目录和 内容 文件夹中的其他内容中。 清单中不需要 <file> 元素。
若要在包中包含自述文件,请使用 readme 元数据元素指定自述文件的目标路径。 此外,使用 file 元数据元素指定自述文件的源路径和目标文件夹。 有关详细信息,请参阅 readme。
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<!-- ... -->
<readme>docs\readme.md</readme>
<!-- ... -->
</metadata>
<files>
<!-- Add a read-me file. -->
<file src="..\readme.md" target="docs\" />
</files>
</package>
Visual Studio在 程序包管理器 UI 中显示说明文件的内容。 例如,以下屏幕截图显示了 HtmlAgilityPack 包的自述文件:
注释
如果在 <files> 文件中包括空节点,NuGet 将包含包中 lib 文件夹的内容,但不包含其他内容。
在软件包中包含 MSBuild 道具及任务目标
在某些情况下,可能需要将自定义生成目标或属性添加到使用包的项目,例如在生成过程中运行自定义工具或进程。 有关自定义生成目标和属性的详细信息,请参阅 包中的 MSBuild .props 和 .targets。
在项目的build文件夹中创建 < 或 >package-id.props 文件,例如 Contoso.Utility.UsefulStuff.targets。
然后在 .nuspec 文件中,在 <files> 节点中引用这些文件:
<?xml version="1.0"?>
<package >
<metadata minClientVersion="2.5">
<!-- ... -->
</metadata>
<files>
<!-- In the package build folder, include everything that's in the local build folder. -->
<file src="build\**" target="build" />
<!-- Other files -->
<!-- ... -->
</files>
</package>
将包添加到项目时,NuGet 会自动包括这些属性和目标。
运行 nuget 包以生成 .nupkg 文件
使用程序集或基于约定的工作目录时,请运行nuget pack 并使用 .nuspec 文件来创建包。 在以下命令中,将 <project-name> 替换为你的项目名称:
nuget pack <project-name>.nuspec
使用Visual Studio项目时,请使用项目文件运行 nuget pack。 此命令会自动加载项目的 .nuspec 文件,并将其中的任何令牌替换为项目文件中的相应值:
nuget pack <project-name>.csproj
注释
对于令牌替换,必须直接使用项目文件,因为项目是令牌值的源。 当与 nuget pack 文件一起使用 .nuspec 时,令牌替换不会成功。
在所有情况下, nuget pack 都排除以句点开头的文件夹,例如 .git 或 .hg。
NuGet 指示 .nuspec 文件中是否有任何需要更正的错误,例如清单中需要更新的占位符值。
在nuget pack成功后,你将拥有一个.nupkg文件,可以根据《发布 NuGet 包》中所述发布到合适的画廊。
小窍门
创建包后检查包的有用方法是在 包资源管理器 工具中打开它。 此工具提供包内容的图形视图及其清单。 还可以将生成的 .nupkg 文件重命名为 .zip 文件,并直接浏览其内容。
附加选项
可以使用各种命令行开关 nuget pack 来排除文件、替代清单中的版本号,以及更改输出文件夹以及其他功能。 有关完整列表,请参阅 pack 命令(NuGet CLI)。
以下选项是Visual Studio项目的一些常见选项:
引用的项目:如果项目引用其他项目,则可以使用
-IncludeReferencedProjects此选项将引用的项目添加为包的一部分或作为依赖项:nuget pack MyProject.csproj -IncludeReferencedProjects此包含过程是递归的。 例如,如果 MyProject.csproj 引用了项目 B 和 C,并且这些项目又引用了 D、E 和 F,那么 B、C、D、E 和 F 中的文件都将包含在包中。
如果引用的项目包含其自身的 .nuspec 文件,NuGet 会将引用的项目添加为依赖项。 需要单独打包和发布该项目。
生成配置:默认情况下,NuGet 使用项目文件中设置的默认生成配置,通常
Debug。 若要从其他生成配置中打包文件,例如Release的, 请使用-properties配置的选项:nuget pack MyProject.csproj -properties Configuration=Release符号:若要包括使使用者能够在调试器中单步执行包代码的符号,请使用
-Symbols和-SymbolPackageFormat选项。 请为-SymbolPackageFormat选项指定snupkg格式:nuget pack MyProject.csproj -symbols -SymbolPackageFormat snupkg
测试包安装
在发布包之前,通常需要测试将包安装到项目中的过程。 测试有助于确保所有必需的文件最终都位于项目中的正确位置。
可以使用标准 package 安装步骤在Visual Studio或命令行中手动测试安装。
对于自动测试,可以使用以下基本过程:
- 将 .nupkg 文件复制到本地文件夹。
- 使用
nuget sources add -name <name> -source <path>命令将文件夹添加到包源。 有关详细信息,请参阅源命令(NuGet CLI)。 只需在任何给定计算机上设置此本地源一次。 - 使用
nuget install <package-ID> -source <name>从该源安装包。 在此命令中,<name>应与在nuget sources命令中使用的源的名称匹配。 指定源会告知 NuGet 仅从该源安装该包。 - 检查文件系统以检查是否已正确安装文件。
相关内容
创建包(即 .nupkg 文件)后,可以将其发布到您选择的画廊。 有关详细信息,请参阅 发布 NuGet 包。
还可以扩展包的功能或支持其他方案。 如需了解更多信息,请参阅以下文章:
若要了解其他包类型,请参阅以下文章: