如何使我的托管NuGet软件包支持C ++ / CLI项目?


77

我制作了一个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文件来执行此操作,但是要使该文件有效,我需要将哪些文件放入文件中?


5
我认为这更多是NuGet中的错误,而不是您需要在程序包中进行调整的错误。看到这个: nuget.codeplex.com/workitem/3665另外,这个问题是相关的:stackoverflow.com/q/18786338/289770
Yodan Tauber

谢谢!有趣的是,在我提出问题的第二天发布了错误报告。我现在投了赞成票。尽管如此,还是有bug还是没有bug,我相信可以使用NuGet脚本解决此问题,并且我正在寻找可以做到这一点的指南。
Tor Hovland 2013年

1
10个月后,但是也许这([ stackoverflow.com/questions/23571241/…)可能会对您有所帮助。[1]:stackoverflow.com/questions/23571241/...
clairestreb

Answers:


32

正如Patrick O'Hara所写,NuGet不会为您更改C ++ / CLI项目。请参阅GitHub Issue NuGet / Home#1121-无法将托管软件包安装到CLI项目中。但是,使用NuGet命令行实用程序,NuGet.exe您可以下载NuGet并解压缩所需的软件包。

对于一个完整的示例,以下是我在Visual Studio 2013 C ++ / CLI项目中添加对OptimizedPriorityQueue 1.0.0的引用的步骤:

  1. 如果尚未打开包管理器控制台,请打开它(工具> NuGet包管理器>包管理器控制台)。
  2. 在程序包管理器控制台中,安装NuGet.CommandLine程序包:

    安装包NuGet.CommandLine
    

    (注意:在撰写本文时,NuGet.CommandLine的最新版本为2.8.6。它可能与您有所不同。)

  3. 在项目文件夹中,现在应该有一个.nuget\packages.config包含以下内容的XML文件:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="NuGet.CommandLine" version="2.8.6" />
    </packages>
    
  4. 在文本编辑器(如Notepad ++)中,<package>为所需的软件包添加一个元素。在这种情况下,我添加了:

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

    ..在<packages>元素内。

  5. 打开命令提示符(我打开了VS2013 Developer命令提示符,但是常规命令提示符应该可以工作。)

  6. cd 到项目文件夹中。
  7. 运行以下命令,如果不同,则更改NuGet.CommandLine的版本号:

    。\ packages \ NuGet.CommandLine.2.8.6 \ tools \ NuGet.exe安装-NonInteractive -OutputDirectory软件包.nuget \ packages.config
    

    对我来说,输出为:

    安装“ OptimizedPriorityQueue 1.0.0.0”。
    成功安装了“ OptimizedPriorityQueue 1.0.0.0”。
    packages.config中列出的所有软件包均已安装。
    
  8. 右键单击Visual Studio中的项目,然后选择“属性”。在“公共属性”>“引用”下,单击“添加新引用...”按钮。
  9. 选择左侧的浏览。在“添加引用”对话框的“确定”和“取消”按钮旁边,有一个“浏览…”按钮。单击该按钮以打开文件选择对话框。
  10. 导航到NuGet解压缩到packages您的项目文件夹的子目录的DLL,然后单击“添加”按钮。单击“确定”关闭“添加引用”对话框。
  11. 现在,您应该可以在C ++ / CLI项目中使用程序集了:


1
@ daniel-trebbien,您如何处理软件包更新?
CodeFox

5
@ daniel-trebbien,有任何线索说明Visual Studio 2017中的步骤8到步骤10是如何执行的?
米哈尔菲塔

在Visual Studio 2013中,这对我来说效果很好。我比创建一个C#虚拟项目并将dll从一个项目复制到另一个更好地喜欢此解决方案。我能够添加NLog 4.0.0。
查尔斯·欧文

非常有帮助,谢谢!仅供参考,当我在VS 2019中执行此操作时,我必须略微更改第7步命令,即在项目的基本目录中创建了packages.config,而不是.nuget文件夹。另外,要在步骤8中看到“浏览”选项,我必须确保为“公共语言运行时支持(/ clr)”配​​置了我的项目,时间:X
Xeozim

7

实际上似乎有可能使用以下步骤(至少使用NuGet >= 2.5)从C ++ / CLI项目中安装并自动引用“常规” NuGet软件包:

  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>
    
  2. .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中的自定义目标将为我们的打包程序添加引用。

据我所知,此解决方案的一个缺点是,以这种方式添加的引用未显示在Commpon Properties/Framework and ReferencesC ++ / CLI项目的部分中。可能还有其他人,使用它需要您自担风险...


6

如该端口的答案所述(Nuget不会将Entity Framework安装到C ++ / CLI项目中),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项目。
希望能有所帮助。


看起来如果我的C ++ / CLI项目是类库(程序集)而不是exe,则nuget仍然会失败。
Weipeng L

@WeipengL这是一个非常老的问题。您的回复缺少细节。也许您应该创建一个描述您的问题并引用该问题的新问题?
Patrick O'Hara

1

安装程序尝试在C#启动项目中添加对自身的引用。在安装之前,将C#项目作为解决方案中的启动项目。如果您没有一个虚拟C#项目


1
C#与C ++ / CLI是不同的东西
rjzii

1

一种简单的解决方法是将这样的NuGet包装在常规的.NET项目(C#)中,并在您的C ++ / CLI项目中对其进行引用。


0

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


-7

凭证实际上是使用添加了程序包源的机器密钥加密的。除非使用明文变体,否则setApiKey命令可能应作为构建的一部分运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.