从Nuget包

时间:2016-10-18 09:43:58

标签: c# asp.net-core nuget nuget-package .net-core

这让我疯狂了几个月,而我仍然无法实现它。我的托管库是从Nuget包中提取的,但不是本地的。

我们有一堆由其他公司提供的托管和本机库。 我们同时拥有x86x64版本。为了在ASP.NET Core项目中使用它们,我必须创建一个Nuget包。

我的架构是:

  • 我改为仅针对完整.NET Framework的ASP.NET Core类库。这个项目引用了我的Nuget Package
  • 一个ASP.NET Core网站,也是针对完整的.NET Framework并引用类库

当然,最后,我需要将我的本机库提取到网站的正确运行时文件夹中(例如:\bin\Debug\net461\win7-x64)。

目前我的解决方案是:

  • 将本机库放在build文件夹
  • 创建一个targets文件,将其复制到$(OutputPath)(甚至不是运行时文件夹)
  • 将一些MsBuild命令添加到我网站的xproj以获取我$(USERPROFILE)\.nuget\packages\文件夹中的目标文件并执行
  • 手动复制 现在在bin文件夹中提取的原生DLL到runtime一个

我尝试使用project.json中的某些配置将它们直接复制到运行时文件夹中(老实说,我不记得我为此部分尝试过的所有内容)但是这个总是失败。即使我在目标文件中指定了SkipUnchangedFiles="true",也只是忽略了这一点,并且在每次构建期间我的DLL都会被复制到我的bin文件夹中。

这是一个重要的过程,只是为了实现DLL提取,现在我真的想摆脱所有的MsBuild并获得一个更简单的解决方案。

我知道Nuget的新版本,它现在能够在没有任何添加自定义MsBuild命令的帮助的情况下原生提取它们。正如here所写,C#项目甚至不需要targets个文件

  

接下来,可能使用NuGet包的C ++和JavaScript项目需要一个.targets文件来识别必要的程序集和winmd文件。 (C#和Visual Basic项目会自动执行此操作。)

我在浏览器中打开了一个标签,持续了几个月(original link),并且最近已经从Nuget网站上删除了此资源。它解释了如何使用runtimes文件夹自动提取本机DLL。但是,正如我所解释的那样,我从来没有能够获得成功的结果。现在,此页面已被删除,并由this one替换,只有很少的解释,而根本没有讨论此runtimes文件夹。

我的猜测是我应该将runtimes文件夹用于本机DLL,将lib文件夹用于托管,但我并非100%确定。 (我也应该使用build文件夹吗?)

我已经尝试了几件事(我无法回想起尝试次数,正如我所说的几个月的头痛......),如this architecture(我不明白这里是什么& #39; s build/native以及runtimes下的原生文件夹 enter image description here

我还尝试将here描述的.NET框架版本结构用于我的托管库。

This似乎也是解决方案的一部分

  

创建程序集引用时,编译器会忽略该体系结构。它是一个加载时间概念。如果存在,加载程序将更喜欢体系结构特定的引用。

     

可以用来生成AnyCPU程序集的一个技巧是使用corflags从x86程序集中删除体系结构。 EG:corflags / 32BITREQ- MySDK.dll。 Corflags是.NET SDK的一部分,可以在VS的开发人员命令提示符中找到。

我做了什么,将x86和x64 DLL都转换为AnyCPU(不知道它是否为x64 DLL做了什么,但我没有得到错误)然后在我的Nuget包中尝试了几种不同的架构,但仍然无法正常工作。

project.json中没有任何条目的默认运行时为win7-x64,因此我决定明确指定它以防万一

"runtimes": {
    "win7-x64": {}
},

所以这是我用于Nuget包中所有尝试的运行时标识符。但是我并不关心Windows版本。我实际上更喜欢使用win-x86或win-x64,但根据this page

它似乎是无效值
  

Windows RID

     

Windows 7 / Windows Server 2008 R2

     
      
  • WIN7-64
  •   
  • WIN7 86
  •   
     

Windows 8 / Windows Server 2012

     
      
  • win8的-64
  •   
  • win8的86
  •   
  • win8的臂
  •   
     

Windows 8.1 / Windows Server 2012 R2

     
      
  • win81-64
  •   
  • win81 86
  •   
  • win81臂
  •   
     

Windows 10 / Windows Server 2016

     
      
  • win10-64
  •   
  • win10 86
  •   
  • win10臂
  •   
  • win10-arm64
  •   

但是这个Github source描述了更多的RID,所以哪个源是正确的?

正如你所看到的,这里有很多谜团,主要是因为缺乏文档甚至是不同文档之间的矛盾。

如果至少我可以有一个工作示例,那么我可以执行我的测试来回答其他问题,例如尝试通用win-x64 RID,或者看看我是否可以包含一次我的托管库,无论.NET Framework版本如何。< / p>

请注意我的特殊背景:我有一个针对完整.NET Framework的ASP.NET核心项目

感谢您的回答,我迫切希望让这个简单的事情发挥作用。

2 个答案:

答案 0 :(得分:21)

我将尝试尽可能详细地解释我所经历的所有痛苦和解决方案。在我的示例中,我使用简单的文本文件AAA86.txtAAA64.txtAAAany.txt而不是本机DLL来简单地演示提取过程。

首先需要知道的事情: 如果您尝试将native NuGet的架构与包含某些托管库的lib文件夹混合使用,它将无效

enter image description here

在这种情况下,您的托管DLL将被复制到项目的输出目录中,但不会复制到您的原生目录。

感谢Jon Skeet向我指出了良好的方向,建议我看看Grpc.Core package。诀窍是创建一个targets文件来处理DLL提取。

enter image description here

您的目标文件应包含类似

的内容
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <ItemGroup Condition=" '$(Platform)' == 'x64' ">
        <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\AAA64.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>AAA64.txt</Link>
        </Content>
    </ItemGroup>

    <ItemGroup Condition=" '$(Platform)' == 'x86' OR '$(Platform)' == 'AnyCPU' ">
        <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x86\native\AAA86.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>AAA86.txt</Link>
        </Content>
    </ItemGroup>

</Project>

现在你需要知道的其他事情很少:

1) Visual Studio 根本不关心您选择的设置,它总是使用虚拟RID。 (就我而言,我总是以win7-x64文件夹结束,即使我在Windows 10上... ...

enter image description here

2) project.json中的platform setting也完全无用

{
    "buildOptions": {
        "platform": "x64"
    }
}

3)如果您只设置win和/或win-x64

,则在runtimes settings
"runtimes": {
    "win": {},
    "win-x64": {}
}

Visual Studio将使用win7-x64。但是如果您在Windows 10计算机上添加win10-x64,则会使用

4)如果使用像这样的通用RID编译应用程序

dotnet build -c debug -r win

然后,您的targets文件将收到您机器的架构(在我的情况下为x64),而不是{I}期待的AnyCPU

5)如果您只有没有任何托管的本机库,那么如果您遵循架构runtimes/RID/native

,则提取将在没有目标文件的情况下工作

6)在我的软件包中只有本机库,选择的RID将永远是win-x64使用Visual Studio构建,因为我告诉你,始终创建的运行时文件夹是win7-x64 ,无论我选择哪种配置。如果我的包中只有一个win个RID,那么它就会被成功挑选出来。

答案 1 :(得分:0)

如今,当您使用dotnet restore而不是nuget.exe restore时,本机DLL无法复制到输出目录的问题就消失了。

在我的情况下,专门使用dotnet restore --runtime win-x64 <path_to_the_solution.sln>可以解决此问题。