gpt4 book ai didi

c# - 从 Nuget 包中自动提取 native 和托管 DLL

转载 作者:IT王子 更新时间:2023-10-29 04:43:14 25 4
gpt4 key购买 nike

这让我疯狂了几个月,但我仍然无法实现它。我的托管库是从 Nuget 包中提取的,但不是从本地库中提取的。
我们有一堆由另一家公司提供的托管和本地库。
我们都有 x86x64他们的版本。为了在 ASP.NET Core 项目中使用它们,我必须创建一个 Nuget 包。
我的架构是:

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

  • 当然,最后,我需要将我的 native 库提取到网站的正确运行时文件夹(例如: \bin\Debug\net461\win7-x64 )。
    目前我的解决方案是:
  • 将 native 库放入 build文件夹
  • 创建 targets将它们复制到 $(OutputPath) 的文件(甚至不是运行时文件夹)
  • 添加一些 MsBuild 命令到 xproj在我的网站中获取目标文件 $(USERPROFILE)\.nuget\packages\文件夹并执行它
  • 复制 手工 现在在 bin 中提取的 native DLL文件夹到 runtime

  • 我尝试使用 project.json 中的一些配置将它们直接复制到运行时文件夹中(老实说,我不记得我为这部分尝试过的所有事情)但这总是失败。即使我指定了 SkipUnchangedFiles="true"在我的目标文件中,这只是被忽略,我的 DLL 会在每次构建期间复制到我的 bin 文件夹中。
    这是一个繁重的过程,只是为了实现 DLL 的提取,现在我真的想摆脱所有 MsBuild 并获得一个更简单的解决方案。
    我知道使用较新版本的 Nuget,它现在能够在本地提取它们,而无需添加自定义 MsBuild 命令。如所写 here , C# 项目甚至不需要 targets文件

    Next, C++ and JavaScript projects that might consume your NuGet package need a .targets file to identify the necessary assembly and winmd files. (C# and Visual Basic projects do this automatically.)


    我在浏览器中打开了一个选项卡几个月 ( original link ) 并意识到此资源最近已从 Nuget 网站上删除。它正在解释如何使用 runtimes文件夹以自动提取 native DLL。但是,我从来没有像解释的那样获得成功的结果。现在该页面已被删除并替换为 this one解释这么少,不谈这个 runtimes文件夹。
    我的猜测是我应该使用 runtimes native DLL 的文件夹和 lib一个用于管理,但我不是 100% 确定。 (我还应该使用 build 文件夹吗?)
    我已经尝试了几件事(我不记得尝试的次数,因为我说几个月的头痛......)比如 this architecture (我不明白这里有 build/native 以及 runtimes 下的 natives 文件夹有什么意义)
    enter image description here
    我还尝试使用 .NET 框架版本结构,如 here 所述对于我的托管库。
    This似乎也是解决方案的一部分

    The architecture is ignored by the compiler when creating an assembly reference. It's a load time concept. The loader will prefer an architecture specific reference if it exists.

    One trick you can use to produce an AnyCPU assembly is to use corflags to remove the architecture from your x86 assembly. EG: corflags /32BITREQ- MySDK.dll. Corflags is part of the .NET SDK and can be found in VS's developer command prompt.


    这就是我所做的,将 x86 和 x64 DLL 都转换为 AnyCPU (不知道它是否对 x64 DLL 起作用,但我没有收到错误)然后在我的 Nuget 包中尝试了几种不同的体系结构,但仍然无法正常工作。
    project.json 中没有任何条目的默认运行时是 win7-x64 ,所以我决定明确指定它以防万一
    "runtimes": {
    "win7-x64": {}
    },
    所以这是我在 Nuget 包中进行所有尝试时使用的运行时标识符。但是我不关心 Windows 版本。我实际上更喜欢使用 win-x86 或 win-x64,但根据 this page,它似乎是一个无效值。

    Windows RIDs

    Windows 7 / Windows Server 2008 R2

    • win7-x64
    • win7-x86

    Windows 8 / Windows Server 2012

    • win8-x64
    • win8-x86
    • win8-arm

    Windows 8.1 / Windows Server 2012 R2

    • win81-x64
    • win81-x86
    • win81-arm

    Windows 10 / Windows Server 2016

    • win10-x64
    • win10-x86
    • win10-arm
    • win10-arm64

    然而这个 Github source正在描述更多的 RID,所以哪个来源是正确的?
    如您所见,这里有很多谜团,主要是因为缺乏文档,甚至不同文档之间存在矛盾。
    如果至少我可以有一个工作示例,那么我可以执行我的测试来回答其他问题,例如尝试通用 win-x64 RID 或看看我是否可以包含一次我的托管库,无论 .NET Framework 版本是什么。
    请注意我的特殊语境: 我有一个针对完整 .NET Framework 的 ASP.NET Core 项目
    感谢您的回答,我非常想让这个简单的事情发挥作用。

    最佳答案

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

    您需要知道的第一件事:
    如果您尝试混合 native NuGet 的架构与 lib包含一些托管库的文件夹,它不会工作

    enter image description here

    在这种情况下,您的托管 DLL 将被复制到您项目的输出目录,而不是您的 native 目录。

    感谢 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>

    还要确保您的 .targets文件的名称与您的 AssemblyName 相同。因此,如果您的程序集名称是 DemoPackage ,你的目标文件应该命名为 DemoPackage.targets .否则, .targets在另一个项目中引用包时可能不会应用文件。
    enter image description here

    现在你需要知道的其他几件事:

    1) Visual Studio 不在乎 完全关于您选择的设置,它将始终使用虚拟 RID。 (就我而言,即使我在 Windows 10 上,我也总是得到一个 win7-x64 文件夹......)

    enter image description here

    2) platform setting在您的 project.json也完全没用
    {
    "buildOptions": {
    "platform": "x64"
    }
    }

    3) runtimes settings如果您只设置 win和/或 win-x64
    "runtimes": {
    "win": {},
    "win-x64": {}
    }

    Visual Studio 将改为使用 win7-x64 .但是如果你加上 win10-x64当你在 Windows 10 机器上时,这将被使用

    4) 如果您使用这样的通用 RID 编译您的应用程序
    dotnet build -c debug -r win

    那么你的 targets文件将接收您机器的架构(在我的情况下为 x64)而不是 AnyCPU正如我所期待的

    5) 仅使用没有任何托管库的 native 库,如果您遵循架构 runtimes/RID/native,提取将在没有目标文件的情况下工作。

    6) 在我的包中只有 native 库时,选择的 RID 将始终是 win-x64正如我告诉您的那样,使用 Visual Studio 构建始终创建的运行时文件夹是 win7-x64 ,无论我选择哪种配置。如果我只有一个 win RID 在我的包中,然后它会成功被选中。

    关于c# - 从 Nuget 包中自动提取 native 和托管 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40104838/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com