向NuGet包contentFiles添加二进制文件致C#项目编译错误
问题场景
在C#项目中引用包含二进制文件(archive.7z)的NuGet包时,执行dotnet build或dotnet publish会触发如下编译错误:
CSC : error CS2015: '...\0.0.14\contentFiles\any\any\archive.7z' is a binary file instead of a text file [...]
需求目标:确保该二进制文件能在构建/发布完成后出现在项目输出目录中。
现有配置细节
.nuspec 文件
<?xml version="1.0"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> ... <contentFiles> <files include="archive.7z" flatten="true" buildAction="None" copyToOutput="true" /> </contentFiles> </metadata> <files> <file src="content/archive.7z" target="contentFiles\any\any" /> </files> </package>
文件夹结构
├───content │ └───archive.7z └───.nuspec
引用包的.csproj 片段
<ItemGroup> <PackageReference Include="my-nuget-package-name" Version="0.0.14" /> </ItemGroup>
错误原因
使用的2010/07版本nuspec schema对contentFiles节点的buildAction属性支持有限,即使设置为None,MSBuild仍会错误地将二进制文件传递给C#编译器,从而触发CS2015错误。
解决方案
方案1:升级nuspec schema版本
将nuspec的xmlns属性升级到2015/06或更高版本,新版本schema能正确识别buildAction="None"的配置,避免编译器处理二进制文件。
修改后的.nuspec头部:
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
保持原有contentFiles和files配置不变,重新打包NuGet包即可。
方案2:改用Build Targets自动复制文件
这是更稳定的跨版本方案,通过NuGet的build targets机制自动配置文件复制逻辑,完全避开contentFiles的兼容性问题:
- 调整NuGet包的文件夹结构,新增
build目录及对应targets文件:
├───content │ └───archive.7z ├───build │ └───my-nuget-package-name.targets └───.nuspec
- 编写
my-nuget-package-name.targets文件内容:
<Project> <ItemGroup> <None Include="$(MSBuildThisFileDirectory)..\content\archive.7z"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>archive.7z</Link> </None> </ItemGroup> </Project>
- 修改.nuspec的
files节点,添加targets文件的打包配置:
<files> <file src="content/archive.7z" target="content" /> <file src="build/my-nuget-package-name.targets" target="build" /> </files>
删除metadata中的contentFiles节点,重新打包后,引用该包的项目会自动执行targets配置,将二进制文件复制到输出目录。
方案3:使用传统content目录(需手动配置项目)
如果不想修改包结构,可将文件打包到传统content目录,然后在引用项目的.csproj中手动添加复制规则:
修改.nuspec的files节点:
<files> <file src="content/archive.7z" target="content" /> </files>
删除metadata中的contentFiles节点,重新打包后,在引用项目的.csproj中添加:
<ItemGroup> <None Include="archive.7z" CopyToOutputDirectory="PreserveNewest" /> </ItemGroup>
推荐方案
优先选择方案1,仅需升级schema版本即可快速解决问题;若需兼容更旧的项目环境,方案2的Build Targets方式更可靠,无需引用方手动配置。
内容的提问来源于stack exchange,提问作者Florian Boehmak

