C# NuGet包文件操作 C#如何创建或解包.nupkg文件

来源:这里教程网 时间:2026-02-21 17:42:41 作者:

NuGet.Packaging
创建 .nupkg 文件

直接调用

NuGet.Packaging
是目前最稳定、可控的方式,比旧版
NuGet.Core
或命令行更适配现代 SDK 风格项目。它不依赖 MSBuild,适合 CI 脚本或工具链集成。

常见错误是误用

NuGet.Packaging.Core
(已废弃)或混淆
NuspecReader
PackageBuilder
的职责——前者只读元数据,后者才真正打包。

安装包:
NuGet.Packaging
≥ 6.0(.NET 6+ 推荐 6.10+,修复了符号包路径 bug)
必须先生成
.nuspec
或用
Manifest
对象构造元数据;不能仅靠文件夹结构自动推断
内容文件需显式添加:用
builder.AddFiles(...)
,路径要相对于包根(如
lib/net6.0/MyLib.dll
),不是绝对路径
若含
tools/
build/
目录,权限位不影响 Windows,但 Linux 下解包可能丢执行位——实际无影响,NuGet 不校验
var builder = new PackageBuilder();
builder.Id = "My.Package";
builder.Version = new NuGetVersion("1.0.0");
builder.Authors.Add("me");
builder.Description = "A demo";
builder.AddFile("bin/Release/MyLib.dll", "lib/net6.0/MyLib.dll");
using var nupkgStream = File.Create("My.Package.1.0.0.nupkg");
builder.Save(nupkgStream);

dotnet pack
解包 .nupkg 文件

dotnet pack
只能打包,不能解包。想“解包”,得用
NuGet.Packaging
PackageReader
,或者临时解压——因为 .nupkg 就是 ZIP,但直接改后缀解压会丢签名(
_rels
[Content_Types].xml
等元数据仍存在,不影响内容读取)。

容易踩的坑是以为

nuget.exe
unpack
命令可用:它从 5.11 起已被移除,且不支持 v3 协议格式的包(即大多数新包)。

推荐做法:用
ZipFile.ExtractToDirectory
快速查看内容,适用于调试或验证结构
若需读取元数据(如依赖项、作者、描述),必须用
PackageReader
,否则解析
.nuspec
容易漏掉自动生成的字段(如
<dependencies></dependencies>
来自
PackageReference
签名验证失败时(
NuGet.Protocol.Core.Types.FatalProtocolException
),不是包损坏,而是你用了带签名的包但没引用
NuGet.Signing
,跳过验证即可
using var stream = File.OpenRead("My.Package.1.0.0.nupkg");
using var reader = new PackageReader(stream);
var metadata = reader.NuspecReader.GetMinimalPackageMetadata();
Console.WriteLine(metadata.Id); // My.Package

处理带符号的 .nupkg(.snupkg)

符号包不是独立格式,只是普通 .nupkg 加了

symbols
标识和特定目录结构(
src/
symbol/
)。创建时别手动塞
.pdb
到任意路径——必须进
src/
并保留原始项目结构,否则调试器找不到源码。

常见误解是认为

dotnet pack --include-symbols
会自动处理所有符号:它只打包当前项目的
.pdb
,不递归打包
ProjectReference
的符号,那些得单独打包并发布到符号服务器。

PackageBuilder
手动加符号:路径必须以
src/
开头,例如
src/MyLib/Program.cs
符号包文件名必须匹配主包名 +
.snupkg
,且
Id
Version
完全一致,否则 NuGet.Server 拒绝索引
本地调试时,VS 默认不查本地文件夹里的 .snupkg——得在选项里启用“仅我的代码”关闭,并添加符号路径到
Tools → Options → Debugging → Symbols

跨平台兼容性与路径陷阱

Windows 上用反斜杠

 构造包内路径(如 
lib
et6.0My.dll
)会导致 Linux/macOS 下读取失败:ZIP 规范强制使用正斜杠
/
NuGet.Packaging
内部会标准化,但手动拼接时若混用,
AddFiles
可能静默跳过文件。

另一个隐形问题是长路径:.nupkg 内路径总长度超 260 字符时,Windows 下

ZipFile.CreateFromDirectory
会报错,但
PackageBuilder
不会——它走的是内存流,不经过文件系统路径检查。

所有包内路径一律用
/
,用
Path.Replace("\", "/")
不可靠,应统一用
Path.GetRelativePath
+
.Replace(Path.DirectorySeparatorChar, '/')
避免在
id
version
中用非法字符(如
/
),NuGet 会抛 <code>ArgumentException
,但错误信息只说“无效的包标识符”,不指明哪部分
Linux 容器里运行打包代码时,若宿主机挂载路径含空格或中文,
File.OpenRead
可能失败——不是编码问题,是 .NET 6+ 对 URI 解码更严格,建议用
Uri.EscapeDataString
处理路径
解包和创建看似简单,但路径分隔符、符号包结构、签名验证这几处,实际跑通一次往往要卡半小时。尤其当包要上私有源或被其他团队引用时,少一个
/
或多一个
src/
层级,下游就拉不到依赖。

相关推荐