Nuget 包不在构建时复制本机 DLL

Nuget package not copying native DLLs on build

我正在尝试创建一个托管库并将其与 Nuget 打包。托管库使用另一个用 C 编写的 DLL,并通过 [DllImport] P/Invoke 调用进行调用。在项目的根目录中,我有一个文件夹结构,如:

我没有使用 .nuspec 文件,而是从 .NET STandard 2.0 项目的 .csproj 文件生成 Nuget 包。我将这些文件包含在 .csproj 文件中。

<ItemGroup>
    <Content Include="runtimes\**" PackagePath="runtimes" Visible="true" />
</ItemGroup>

nuget 包在 lib/netstandard2.0 目录中有托管 DLL,甚至在 root/runtimes/RID/native 目录中有非托管 DLL。使用这个 nuget 包的项目安装完美,构建没有错误。

消费者将与之交互的托管 DLL 正在尝试像这样使用本机 DLL

[DllImport("file_name.dll")]
private static extern IntPtr CscanHOpen(string connectionString);
//...
public void Open(string connectionString, int port) {
    _handle = CscanHOpen(connectionString, port);
}

我在安装 nuget 包的项目中收到 "file cannot be found" 错误,当我查看构建目录时,我在那里没有看到非托管 DLL。我试过使用目标文件将非托管 DLL 复制到使用项目的输出目录,但它从未出现。

我一直在回头看这个问题,因为没有答案,所以我要重复我们在评论中讨论的内容。

NuGet 的 runtimes 功能仅适用于使用带有 PackageReference 包的项目,不适用于 packages.config。事实上,尽管我在 NuGet 客户端团队,但我不确定 runtimes 是否是 SDK-style 项目功能,或者它是否也适用于传统项目。老实说,我希望它只适用于 SDK 风格的项目,因为它需要构建系统的其余部分知道如何使用这些资产。

因此,您的问题的答案是使用 SDK-style 项目测试您的包。所有 .NET Core 应用程序都是 SDK 样式,但您也可以编辑项目并将 <TargetFramework>netcoreapp2.2</TargetFramework> 更改为 `net48,或者将 xml 标记设为复数并将值设为 semi-colon 分隔的 TFM 列表.

另请注意,class 库没有主机,因此没有 RID。因此您可能看不到 运行time dll。您需要确保使用该包的测试项目具有主机和入口点,例如控制台应用程序。

要支持 packages.config 项目(可能还有使用 PackageReference 的传统项目),您需要 bundle your own props and targets file in the package. You said you tried it, but it didn't work, which unfortunately just means you were doing it wrong. NuGet has a convention on how you must name your props and targets file. If you got that right, then the way you implemented copying the files didn't work. You can use MSBuild's increased verbosity, or msbuild -bl coupled with the MSBuild structured log viewer 调试目标文件。

使用 runtimes 功能是如此罕见,我真的没有任何经验,也不知道如何支持这两个传统项目,同时使用 SDK 中的集成 runtimes 支持风格的项目。我建议您需要确保您的目标只有在不是 SDK 样式项目时才具有 运行 条件,但我不知道您如何检测到它。