Nuget包在构建时无法复制本地DLL文件

4

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

  • root/runtimes/win-x86/native/file.dll
  • root/runtimes/win-x64/native/file.dll

我没有使用.nuspec 文件,而是从.NET标准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包时遇到了“找不到文件”的错误提示,当我查看构建目录时,发现没有那个非托管DLL文件。我尝试使用targets文件将非托管DLL文件复制到消费项目的输出目录中,但它从未出现。


请查看 obj/project.assets.json 文件。文件顶部有两个部分(json键):targetslibrarieslibraries 部分列出了包中的所有文件,因此即使您在其中找到了 dll 文件,也没有任何意义。请在文件的 targets 部分中查找您的包。它应该具有编译和运行时属性,其中包含 NuGet 选择的任何文件。如果您的本机 dll 没有列出,则 .net sdk 的其余部分将不会知道它。资产文件还应提供有关项目存在哪些 RID 的提示(请查看 targets 对象的直接子项)。 - zivkan
正在使用Nuget包的项目是.NET Framework 4.7.2类库项目(NUnit测试)。当我查看obj文件夹时,发现没有project.assets.json文件。这个文件只会为.NET Core/Standard项目创建吗? - Logan K
它是由 ProjectReference (PR) 项目创建的,可以是 SDK 样式或传统的项目文件。 packages.config 项目不支持 NuGet 的运行时内容。我不确定在使用 PR 的传统项目中是否适用。最好的方法是使用 SDK 样式项目(创建一个 .NET Core 项目,然后编辑 csproj 并将目标框架更改为 net472)。 - zivkan
另外,我不确定类库是否考虑运行时资源,因为它们并不是设计成可执行文件的。最好使用控制台应用程序进行测试。 - zivkan
我认为你是正确的。乍一看,当我创建一个.NET Core应用程序时,它会将运行时文件夹从Nuget包复制到构建目录中。我今晚或明天早上会进一步研究这个问题,并告诉你是否有足够的信息来解决这个问题。 - Logan K
这似乎是正确的。如果它是一个类库项目,它似乎不起作用。但是,如果我做一个.NET Core或.NET Framework项目,它将把非托管库复制到使用项目的输出目录。 - Logan K
1个回答

3

我不断地回顾这个问题,因为没有答案,所以我要重复一下我们在评论中讨论的内容。

NuGet的runtimes功能仅适用于使用PackageReference的项目,而不是packages.config。实际上,尽管我在NuGet客户端团队工作,但我并不确定runtimes是否是SDK样式项目的特性,或者它是否也适用于传统项目。老实说,我认为它仅适用于SDK样式项目,因为它需要其他构建系统知道如何使用这些资产。

因此,回答您的问题是使用SDK样式项目测试您的软件包。所有.NET Core应用程序都是SDK样式的,但您也可以编辑项目并将<TargetFramework> netcoreapp2.2 </TargetFramework>更改为"net48",或使xml标签复数,并将值设置为分号分隔的TFM列表。

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

要支持packages.config项目(以及可能使用PackageReference的传统项目),您需要在软件包中捆绑自己的props和targets文件。您说您尝试过了,但它没有起作用,这不幸的是意味着您做错了。NuGet有一个惯例,说明您必须如何命名您的props和targets文件。如果您做对了,那么您实现复制文件的方式可能是错误的。您可以使用MSBuild的增加详细程度,或者将msbuild -blMSBuild结构化日志查看器配对来调试您的目标文件。

使用runtimes功能非常不常见,我实际上没有任何经验,并且不知道如何在同时使用SDK样式项目中集成runtimes支持时支持传统项目。我建议您需要确保您的目标具有条件,仅在不是SDK样式项目时运行,但我不知道您如何检测到它。


我必须再仔细研究一下 props 和 targets 文件。如果我做错了什么,我不会感到惊讶,因为感觉自己只是在胡乱尝试。找到任何可行的方法,如果不起作用就转向下一个。再次感谢。 - Logan K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接