.net 如何让我的托管NuGet包支持C++/CLI项目?

roejwanj  于 2023-03-20  发布在  .NET
关注(0)|答案(8)|浏览(215)

我做了一个NuGet包,当我从C#项目中使用它时,它工作得很好。它在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文件来完成这项工作,但是我需要在这些文件中放入什么才能完成这项工作呢?

ax6ht2ek

ax6ht2ek1#

作为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的引用时所采取的步骤,作为一个完整的示例:
1.打开软件包管理器控制台(如果尚未打开)(工具〉NuGet软件包管理器〉软件包管理器控制台)。
1.在程序包管理器控制台中,安装NuGet.CommandLine程序包:

Install-Package NuGet.CommandLine

(Note:在撰写本文时,NuGet.CommandLine的最新版本是2. 8. 6。它可能与您的版本不同。)
1.在项目文件夹中,现在应该有一个.nuget\packages.config XML文件,其内容如下:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="NuGet.CommandLine" version="2.8.6" />
</packages>

1.在文本编辑器(如Notepad++)中,为所需的包添加<package>元素。

<package id="OptimizedPriorityQueue" version="1.0.0" />

..在<packages>元素内。
1.打开命令提示符(我打开了VS 2013开发人员命令提示符,但常规命令提示符应该可以工作。

  1. cd到项目文件夹中。
    1.运行以下命令,并更改NuGet.CommandLine的版本号(如果不同):
.\packages\NuGet.CommandLine.2.8.6\tools\NuGet.exe Install -NonInteractive -OutputDirectory packages .nuget\packages.config

对我来说,结果是:

Installing 'OptimizedPriorityQueue 1.0.0.0'.
Successfully installed 'OptimizedPriorityQueue 1.0.0.0'.
All packages listed in packages.config are already installed.

1.在Visual Studio中右键单击项目并选择属性。在公共属性〉引用下,单击添加新引用...按钮。
1.选择左手的
浏览
。在添加引用对话框的确定和取消按钮旁边,有一个浏览...按钮。单击该按钮打开文件选择对话框。
1.导航到NuGet解压缩到项目文件夹的packages子目录中的DLL,然后单击
Add
按钮。单击OK关闭Add Reference对话框。
1.现在应该可以在C++/CLI项目中使用该程序集了:

using namespace Priority_Queue;

//...
dauxcl2d

dauxcl2d2#

实际上似乎有可能使用以下步骤(至少使用NuGet >= 2.5)安装“常规”NuGet包并从C++/CLI项目中自动引用:
1.在您要打包的项目中添加(或修改)一个build\<ProjectName>.targets文件,并放入以下内容(确保将<AssemblyName>替换为实际值):

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- for C++/CLI projects only -->
  <ItemGroup Condition="'$(Language)' == 'C++'">
    <Reference Include="<AssemblyName>">
      <!--
        this .targets file is installed next to the assembly,
        so we do not have to figure out any versions or paths here ourselves
      -->
      <HintPath>
        $(MSBuildThisFileDirectory)..\lib\native\<AssemblyName>.dll
      </HintPath>
    </Reference>
  </ItemGroup>
</Project>

1.在打包项目的.nuspec中,添加一个或多个file条目,以便也将程序集放置在目标计算机的lib\native\目录中:

<package>
  <metadata>
    ...
  </metadata>
  <files>
    ...
    <!--
      add a copy of the assembly to lib\native to prevent NuGet
      from complaining about incompatible native projects
    -->
    <file src="bin\$configuration$\$id$.dll" target="lib\native\" />
    <file src="bin\$configuration$\$id$.xml" target="lib\native\" />

    <!-- don't forget about the .targets file containing the reference -->
    <file src="build\$id$.targets" target="build\" />
  </files>
  ...
</package>

即使NuGet不向C++/CLI项目添加汇编引用,它仍然会插入包提供的任何.props.targets文件,并且步骤1中的自定义目标将向我们打包的汇编添加引用。
这个解决方案的一个缺点,据我所知,是以这种方式添加的引用没有显示在C++/CLI项目的Commpon Properties/Framework and References部分中。可能还有其他的,所以使用它要自担风险...

rdlzhqv9

rdlzhqv93#

正如在对这个端口(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项目中。
希望能有所帮助。

2uluyalo

2uluyalo4#

简单的解决方法是将此类NuGet Package 在常规的.NET项目(C#)中,并在C++/CLI项目中引用相同的内容。

n53p2ov0

n53p2ov05#

安装程序尝试在C#启动项目中添加对自身的引用。安装前,请将C#项目设置为解决方案中的启动项目。如果没有,请创建一个伪C#项目

b91juud3

b91juud36#

我这里的解决方案并没有使为Cli项目添加Nuget包支持变得更容易,但是它允许我将Nuget包添加到我的Cli包中。
我得到的错误:当我试图安装OptiPlot.WPF或NuGet. Commandline时,“您试图将此包安装到目标为”native,Version= v0.0“的项目中,但该包不包含任何与该框架兼容的程序集引用或内容文件。”
这可能不是一个能满足所有人需求的完整解决方案,但它对我很有效。我找到了一种“作弊”的方法,将OptiPlot.WPF放入一个示例C++.Net项目中。我的解决方案中有一个C#主程序项目-我在那里安装了这个包:安装包OxyPlot.Wpf -版本2.0.0
然后我把packages.config文件和packages文件夹从那里复制到我的C++ .Net类库项目中,然后我编辑packages.config文件,去掉一些不适用的东西,我可能去掉了packages中不需要的一个包,然后我把C++ .Net类库项目中的引用添加到packages/OxyPlot.Wpf.2.0.0文件夹中。
现在我可以在C++里面使用OxyPlot了!酷!

fv2wmkja

fv2wmkja7#

上面的答案存在二级依赖项的问题(至少在我使用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>

然后,整个packages文件夹将通过c++/cli项目中的自定义任务进行部署。
如果引用的包针对AnyCPU,则此解决方案是合适的,否则需要进行一些修补,以便为每个处理器架构使用不同的文件夹,并且可能不会起作用。
这个解决方案并不优雅,但是解决了从c++/cli项目中可靠地(间接地)使用nuget包的目的。
这个解决方案相对于这里发布的其他解决方案的优点是,路径没有版本控制,因此在正常的包升级过程中,c++/cli项目永远不会改变。

m528fe3b

m528fe3b8#

凭据实际上是用添加包源代码的机器密钥加密的。除非使用明文变体,否则setApiKey命令应该作为构建的一部分运行。

相关问题