当我从 C# 项目中使用它时,我制作了一个运行良好的 NuGet 包。它在 lib/net40
目录中包含一个 DLL,该 DLL 被添加为参考。
现在 NuGet 支持 C++,我如何实际修改我的包,以便可以将 DLL 作为托管引用添加到 C++/CLI 项目中?我找不到任何解释这一点的教程。如果我尝试按原样添加包,则会收到以下错误:
您正在尝试将此包安装到以“Native,Version=v0.0”为目标的项目中,但该包不包含任何与该框架兼容的程序集引用或内容文件。
有人会认为解决方案是将文件放在 lib/native 下,但根据 http://docs.nuget.org/docs/reference/support-for-native-projects,这是不支持的。此外,简单地将 DLL 直接放在 lib 下似乎没有任何作用。
显然,我应该使用 build/native 下的 .props
或 .targets
文件来执行此操作,但是我需要在这些文件中添加什么才能使其正常工作?
作为 Patrick O'Hara wrote,NuGet 不会为您更改 C++/CLI 项目。见GitHub Issue NuGet/Home#1121 - Cannot install managed packages into a CLI project。但是,使用 NuGet 命令行实用程序 NuGet.exe
,您可以让 NuGet 下载并解压缩所需的包。
对于一个完整的示例,以下是我在 Visual Studio 2013 C++/CLI 项目中添加对 OptimizedPriorityQueue 1.0.0 的引用的步骤:
如果尚未打开包管理器控制台,请打开(工具 > NuGet 包管理器 > 包管理器控制台)。在包管理器控制台中,安装 NuGet.CommandLine 包:Install-Package NuGet.CommandLine (注意:在撰写本文时,NuGet.CommandLine 的最新版本是 2.8.6。它可能对您有所不同。)在您的项目中文件夹,现在应该有一个 .nuget\packages.config XML 文件,其内容如下:
实际上,似乎有可能使用以下步骤(至少使用 NuGet >= 2.5
)从 C++/CLI 项目中安装和自动引用“常规”NuGet 包:
将 build\
即使 NuGet 不向 C++/CLI 项目添加程序集引用,它仍会插入包提供的任何 .props
和 .targets
文件。步骤 1 中的自定义目标将添加对我们打包程序集的引用。
据我所知,此解决方案的一个缺点 是以这种方式添加的引用不会显示在 C++/CLI 项目的 Commpon Properties/Framework and References
部分中。可能还有其他人,所以使用它需要您自担风险...
如对此端口 (Nuget won't install Entity Framework into C++/CLI project) 的答复中所述,NuGet 不会为您更改 C++/CLI 项目。但是,它将为您下载并解包依赖项。我们从命令行使用它作为我们的 make 依赖项的一部分。命令行将如下所示:
/.NuGet/NuGet.exe
Install
-NonInteractive
-ConfigFile $ENV{SRC_ROOT}/.nuget/NuGet.config
-OutputDirectory $ENV{SRC_ROOT}/packages
$ENV{SRC_ROOT}/packages.config
请注意,命令行参数是逐行分隔的,以便于阅读。我们还决定在 .NuGet 文件夹中将 NuGet 检入我们的源代码控制中。目标是更容易为我们的各种环境(并非所有环境都使用 Visual Studio)设置构建机器。首次运行此命令后,必须手动将依赖项添加到 C++/CLI 项目中。希望有帮助。
简单的解决方法是将此类 NuGet 包装在常规 .NET 项目 (C#) 中,并在 C++/CLI 项目中引用相同的内容。
安装程序尝试在 C# 启动项目中添加对自身的引用。在安装之前将 C# 项目作为解决方案中的启动项目。如果没有,请创建一个虚拟 C# 项目
我的解决方案不会更容易为 Cli 项目添加 Nuget 包支持,但它允许我将 nuget 包添加到我的 Cli 包中。
我收到错误消息:“您正在尝试将此包安装到以 'native,Version=v0.0' 为目标的项目中,但该包不包含任何与该框架兼容的程序集引用或内容文件。”当我尝试安装 OptiPlot.WPF 或 NuGet.Commandline 时。
这可能不是满足每个人需求的完整解决方案,但它对我有用。我发现了一种将 OptiPlot.WPF 放入示例 C++.Net 项目的“作弊”方式。我的解决方案中有一个 C# 主程序项目 - 我在那里安装了包:Install-Package OxyPlot.Wpf -Version 2.0.0
然后我将 packages.config 文件和 packages 文件夹从那里复制到我的 C++ .Net 类库项目中。然后我编辑了packages.config文件,取出了一些不适用的东西,我可能在不需要的包中取出了一个包。然后我将 C++ .Net 类库项目中的引用添加到 packages/OxyPlot.Wpf.2.0.0 文件夹。
现在我可以在 C++ 中使用 OxyPlot!凉爽的!
上面的答案存在二级依赖问题(至少在我的 Visual Studio 2019 上)。
为了解决这个问题,我通常创建一个空的 c# 控制台应用程序并引用那里的所有包。
然后,我使用此构建后代码段将项目主要工件以外的所有内容复制到解决方案文件夹中名为 packages
的公共存储中。
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<PropertyGroup>
<SharedLibraries>$(SolutionDir)\packages</SharedLibraries>
</PropertyGroup>
<ItemGroup>
<Artifacts Include="$(OutDir)\**" />
</ItemGroup>
<RemoveDir Condition=" Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />
<MakeDir Condition=" !Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />
<Copy SourceFiles="@(Artifacts)" DestinationFolder="$(SharedLibraries)\%(RecursiveDir)" />
<ItemGroup>
<ExtraFiles Include="$(SharedLibraries)\$(ProjectName).*"></ExtraFiles>
</ItemGroup>
<Delete Files="@(ExtraFiles)" />
</Target>
然后使用 c++/cli 项目中的自定义任务部署整个 packages
文件夹。
如果引用的包以 AnyCPU
为目标,则此解决方案适用,否则需要进行一些修改才能为每个处理器体系结构使用不同的文件夹,并且可能无法正常工作。
此解决方案并不优雅,但解决了从 c++/cli 项目可靠地使用 nuget 包(间接)的目的。
此解决方案相对于此处发布的其他解决方案的优点是路径没有版本控制,因此在正常包升级期间不会更改 c++/cli 项目。
凭据实际上是使用添加包源的机器密钥加密的。除非使用明文变体,否则 setApiKey 命令可能应该作为构建的一部分运行。