NuGet パッケージからネイティブ DLL とマネージド DLL を自動的に抽出する 質問する

NuGet パッケージからネイティブ DLL とマネージド DLL を自動的に抽出する 質問する

数か月間、このことで頭がおかしくなりそうでしたが、まだ実現できていません。管理ライブラリは NuGet パッケージから抽出されていますが、ネイティブのライブラリは抽出されていません。

他社から提供されたマネージド ライブラリとネイティブ ライブラリが多数あります。両方のバージョンx86がありますx64。ASP.NET Core プロジェクトでそれらを使用するには、Nuget パッケージを作成する必要があります。

私のアーキテクチャは次のとおりです。

  • ASP.NET Coreクラスライブラリをフル.NET Frameworkのみを対象に変更しました。このプロジェクトはNugetパッケージを参照します
  • 完全な.NET Frameworkをターゲットとし、クラスライブラリを参照するASP.NET Core Webサイト

もちろん、最後に、ネイティブ ライブラリを Web サイトの適切なランタイム フォルダー (例: \bin\Debug\net461\win7-x64) に抽出する必要があります。

現時点での私の解決策は次のとおりです。

  • buildネイティブライブラリをフォルダ内に置く
  • targetsそれらを$(OutputPath)(ランタイムフォルダではない)にコピーするファイルを作成します。
  • xproj私のウェブサイトにいくつかのMsBuildコマンドを追加して、$(USERPROFILE)\.nuget\packages\フォルダ内のターゲットファイルを取得して実行します。
  • コピー手でネイティブDLLがbinフォルダに抽出されruntime

いくつかの設定を使用してそれらをランタイム フォルダーに直接コピーしようとしましたがproject.json(正直、この部分で試したことをすべて覚えているわけではありません)、常に失敗しました。また、ターゲット ファイルで指定したにもかかわらずSkipUnchangedFiles="true"、これは無視され、ビルドごとに DLL が bin フォルダーにコピーされます。

これは DLL の抽出を実現するだけでも大変なプロセスなので、MsBuild をすべて取り除き、よりシンプルなソリューションを実現したいと考えています。

Nugetの新しいバージョンでは、カスタムMsBuildコマンドを追加しなくてもネイティブに抽出できるようになりました。ここtargetsC#プロジェクトではファイルさえ必要ありません

次に、NuGet パッケージを使用する可能性のある C++ および JavaScript プロジェクトでは、必要なアセンブリ ファイルと winmd ファイルを識別するために .targets ファイルが必要です (C# および Visual Basic プロジェクトでは、これが自動的に実行されます)。

私は数か月間ブラウザでタブを開いたままにしていました(オリジナルリンク) で、このリソースが最近 Nuget の Web サイトから削除されたことに気づきました。このリソースでは、フォルダーを使用してネイティブ DLL を自動的に抽出する方法が説明されていましたruntimes。しかし、説明どおりに成功したことはありません。現在、このページは削除され、これです説明がほとんどなく、このruntimesフォルダについては全く触れられていません。

runtimes私の推測では、ネイティブ DLL 用のフォルダーとマネージ DLL 用のフォルダーを使用する必要があるのですlibが、100% 確信はありません。(フォルダーも使用する必要がありますかbuild?)

私はいくつかのことを試しました(何ヶ月も頭痛がしたので、何回試したかは覚えていません...)この建築build/native(と natives フォルダを の下に持つ意味がわかりませんruntimes)ここに画像の説明を入力してください

また、.NETフレームワークのバージョン構造を説明したように使用してみました。ここ管理しているライブラリ用です。

これ解決策の一部でもあるようだ

アセンブリ参照を作成するとき、アーキテクチャはコンパイラによって無視されます。これはロード時の概念です。ローダーは、存在する場合、アーキテクチャ固有の参照を優先します。

AnyCPU アセンブリを生成するために使用できる 1 つの方法は、corflags を使用して x86 アセンブリからアーキテクチャを削除することです。例: corflags /32BITREQ- MySDK.dll。corflags は .NET SDK の一部であり、VS の開発者コマンド プロンプトにあります。

私がやったのは、x86 DLL と x64 DLL の両方をAnyCPU(x64 DLL に対して何か効果があるかどうかはわかりませんが、エラーは発生しませんでした) に変換し、Nuget パッケージでいくつかの異なるアーキテクチャを試しましたが、まだ動作しません。

project.jsonに何も入力されていない場合のデフォルトのランタイムは なのでwin7-x64、念のため明示的に指定することにしました。

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

これが、私がNugetパッケージで試すすべてのものに使用しているランタイム識別子です。ただし、Windowsのバージョンは気にしません。実際にはwin-x86またはwin-x64の方が良いのですが、このページ

Windows RID

Windows 7 / Windows Server 2008 R2

  • Windows7-x64 の場合
  • Windows7-x86 の場合

Windows 8 / Windows Server 2012

  • Windows8-x64 の場合
  • Windows8-x86 の場合
  • win8-アーム

Windows 8.1 / Windows Server 2012 R2

  • Windows81-x64 の場合
  • Windows81-x86 の場合
  • win81アーム

Windows 10 / Windows Server 2016

  • Windows10-x64 の場合
  • Windows10-x86 の場合
  • win10-アーム
  • win10-arm64

しかし、これはGithubソースより多くの RID について説明していますが、どのソースが正しいのでしょうか?

ご覧のとおり、ここには多くの謎がありますが、その主な原因はドキュメントの不足、あるいは異なるドキュメント間の矛盾です。

少なくとも実用的な例があれば、汎用win-x64RID を試したり、.NET Framework のバージョンに関係なくマネージ ライブラリを一度に含めることができるかどうかを確認したりするなど、他の質問に答えるためのテストを実行できます。

私の特別な状況に注意してください:完全な.NET FrameworkをターゲットとしたASP.NET Coreプロジェクトがあります

ご回答ありがとうございます。この単純なことを何とか実現したいのです。

ベストアンサー1

私が経験したすべての苦労と解決策を、できるだけ詳しく説明したいと思います。私の例では、抽出プロセスを簡単に説明するために、ネイティブ DLL ではなく、単純なテキスト ファイルを使用しAAA86.txtます。AAA64.txtAAAany.txt

まず知っておくべきこと:nativeNuGetのアーキテクチャとlibいくつかのマネージドライブラリを含むフォルダを混在させようとすると、うまくいかないだろう

ここに画像の説明を入力してください

その場合、マネージ DLL はプロジェクトの出力ディレクトリにコピーされますが、ネイティブ DLL はコピーされません。

私に良い方向を示してくれたジョン・スキートに感謝します。Grpc.Core パッケージ秘訣は、targetsDLL の抽出を処理するファイルを作成することです。

ここに画像の説明を入力してください

ターゲットファイルには次のような内容が含まれている必要があります

<?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>

また、ファイル名が AssemblyName と同じであることを確認してください.targets。アセンブリ名が の場合DemoPackage、ターゲット ファイル名は にする必要がありますDemoPackage.targets。そうしないと、.targets別のプロジェクトでパッケージを参照するときにファイルが適用されない可能性があります。ここに画像の説明を入力してください

他に知っておくべきことがいくつかあります:

1)ビジュアルスタジオ気にしない選択した設定に関係なく、常にダミーの RID が使用されます。(私の場合は、win7-x64Windows 10 を使用しているにもかかわらず、常にフォルダーが作成されます...)

ここに画像の説明を入力してください

2)プラットフォーム設定あなたのproject.jsonも全く役に立たない

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

3)の中にランタイム設定winおよび/またはのみを設定する場合win-x64

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

Visual Studioは代わりに を使用しますwin7-x64。ただし、win10-x64Windows 10マシンで追加した場合は、これが使用されます。

4)アプリケーションを次のような汎用RIDでコンパイルすると

dotnet build -c debug -r win

そうすると、ファイルは私が期待していたもののtargets代わりに、マシンのアーキテクチャ(私の場合はx64)を受け取ります。AnyCPU

5)ネイティブライブラリのみでマネージドライブラリがない場合、アーキテクチャに従えばターゲットファイルなしで抽出が機能します。runtimes/RID/native

6)パッケージにネイティブ ライブラリのみが含まれている場合、選択した RID は常にwin-x64Visual Studio でビルドされます。これは、選択した構成に関係なく、ランタイム フォルダーが常に作成されるためですwin7-x64。パッケージに RID が 1 つだけ含まれている場合はwin、正常に選択されます。

編集:

最後に、このようなタスクを実行するときは、.targets次のようにファイルが実行される現在のディレクトリを印刷すると便利かもしれません。

<Target Name="TestMessage" AfterTargets="Build" >
    <Message Text="***********************************************************" Importance="high"/>
    <Message Text="$(MSBuildThisFileDirectory)" Importance="high"/>
    <Message Text="***********************************************************" Importance="high"/>
</Target>

ディレクトリはBuildVisual Studioの出力に印刷されます。

おすすめ記事