ネイティブDLLをビンフォルダーにコピーするより良い方法はありますか?

StackOverflow https://stackoverflow.com/questions/3863419

質問

ネイティブ(C ++)DLLから関数を呼び出すC#ラッパーコードがあります。現在、C#DLLへの参照を追加して、「コピーローカル」オプションをtrueに設定できます。ただし、依存関係であるネイティブDLLは参照として追加できないため、「ローカル」オプションはありません。

私は次のアプローチを試しました

  1. ビルド後のイベントを使用して、ネイティブDLLをLIBSフォルダーから $(TargetFolder)

    copy "$(ProjectDir)Libs\NQuantLibc.dll" "$(TargetDir)NQuantLibc.dll"

  2. ネイティブDLLをプロジェクトの既存のアイテムとして含めました(追加 - >既存のアイテム - > dllを含む)。このオプションを使用すると、「Copy Local」オプションを使用できます。このアプローチの欠点は、DLLが常にプロジェクトアイテムとして表示されることです。

また、Libsフォルダーを見ることができる「すべてのファイルを表示」しました。次に、プロジェクトにnquantlibc.dllファイルを含め、「コピーローカル」オプションを設定できるようにします。しかし、これは私に予想外の結果をもたらしました。ビンフォルダー内にDLLを含むLIBSサブフォルダーを作成しました(例: bin/debug/Libs/NQuantLibc.dll)。 C#DLLがネイティブDLLを適切に呼び出すことができなかったため、理想的ではありません。

上記の両方のオプションの両方が機能します。依存関係が常に解決されるように、ネイティブDLLをビンフォルダーにコピーするより良い方法はありますか?または、このタイプのシナリオに別のアプローチがありますか?

役に立ちましたか?

解決

プロジェクト +既存のアイテムを追加し、DLLを選択します。ソリューションエクスプローラーウィンドウで追加されたファイルを選択します。 [プロパティ]ウィンドウで、コピーを出力ディレクトリ設定に変更して、「新しい場合はコピー」に変更します。

他のヒント

ネイティブDLLをリンクされたアイテムとして追加して、使用できます」新しい場合はコピーします".
ネイティブDLLの問題は、プロジェクトの構成(デバッグ/リリースまたはプラットフォーム)に応じて、異なるDLLを使用する場合があることです。

プロジェクトの.csprojを編集して、ネイティブDLLを条件付きでリンクできます。

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
    <Content Include="..\..\bin\Win32\Release\NQuantLibc.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
 </ItemGroup>   
 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
    <Content Include="..\..\bin\Win32\Debug\NQuantLibc_d.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
    <Content Include="..\..\bin\x64\Debug\NQuantLibc_d.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
    <Content Include="..\..\bin\x64\Release\NQuantLibc.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

注コピーオプションはに設定されています PRESERVENEWest つまり、「新しい場合はコピー」を意味します。

より良い方法を見つけました。 nugetは.targetsファイルを追加できます。魔女は、パッケージのビルドフォルダーにプロジェクトに保存されます。このようにすると、各パッケージのファイルを作成するたびにコピーできます。次の例では、いくつかの非ドットネットDLLを「バイナリ」フォルダーに保存しました。各ビルドで、DLLが出力フォルダー($ outputPath変数)に既にコピーされているかどうかを確認し、必要に応じてそれらをコピーします。

ヌスペックコンテンツ:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>Example</id>
        <version>1.0.0</version>
        <authors>Example</authors>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Example</description>
    </metadata>
    <files>
        <file src="Non-DotNet.dll" target="binaries\Non-DotNet.dll" />
        <file src="DotNet.dll" target="lib\net40\DotNet.dll" />
        <file src="Example.targets" target="build\Example.targets" />
    </files>
</package>

example.targetsコンテンツ:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="CopyBinaries" BeforeTargets="BeforeBuild">
        <CreateItem Include="$(MSBuildThisFileDirectory)..\binaries\**\*.*">
            <Output TaskParameter="Include" ItemName="PackageBinaries" /> 
        </CreateItem>

        <Copy SourceFiles="@(PackageBinaries)"
              DestinationFolder="$(OutputPath)"
              SkipUnchangedFiles="true"
              OverwriteReadOnlyFiles="true"
        />
    </Target>
</Project>

プロジェクトのファイルとしてDLLを追加します(「リンクとして」別のディレクトリに存在したい場合)。次に、Build Actionをコンテンツに設定し、Trueに出力ディレクトリにコピーします。

作成された「libs」フォルダーで大丈夫なら、に追加してみてください 調査パス あなたのアプリケーションのために、 app.config ファイル:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="Libs;Bin2"/>
      </assemblyBinding>
   </runtime>
</configuration>

これにより、ランタイムはDLLの指定されたすべてのディレクトリを調べます。

編集 残念ながら、これ Dllimportによる管理されていないDLLロードに影響を与えません.

どうやら私はたまたま同じ問題を抱えていたようですが、プロジェクトファイルの編集をあまりやりたくなかったので、次のビルド後のスクリプトを使用することになりました。

xcopy /y "$(ProjectDir)\lib_$(Platform)\*.dll" "$(ProjectDir)$(OutDir)"

必要なターゲティングプラットフォームごとにフォルダーがあることを確認してください。 lib_x86, lib_x64 そして多分 lib_AnyCPU

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top