21

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

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

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

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

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

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

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

4

6 に答える 6

32

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

于 2010-10-05T14:06:22.127 に答える
18

ネイティブ dll をリンクされたアイテムとして追加し、「Copy if newer」を使用できます。
ネイティブ 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に設定されていることに注意してください。これは、「新しい場合はコピーする」ことを意味します。

于 2015-10-30T13:15:50.310 に答える
6

より良い方法を見つけました。Nuget は、パッケージのビルド フォルダーに格納されている .targets ファイルをプロジェクトに追加できます。このようにして、各ビルドでパッケージのいくつかのファイルを好きな場所にコピーできます。次の例では、非 DotNet DLL を「binaries」フォルダーに保存しています。ビルドごとに、DLL が既に出力フォルダー ($OutputPath 変数) にコピーされているかどうかを確認し、必要に応じてコピーします。

Nuspec コンテンツ:

<?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>
于 2015-10-01T07:36:20.383 に答える
1

プロジェクトにファイルとしてdllを追加します(別のディレクトリに存在させたい場合は、「リンクとして」かもしれません)。次に、Build Action を content に、Copy to output directory を true に設定します。

于 2010-10-05T12:10:06.527 に答える
1

作成された「Libs」フォルダーに問題がない場合は、ファイルに次を追加して、アプリケーションのプローブ パスに追加してみてください。app.config

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

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

EDIT残念ながら、これは DllImport によるアンマネージ DLL の読み込みには影響しません

于 2010-10-05T12:13:53.023 に答える