8

System.IO.FileNotFoundException: The specified module could not be foundC++/CLI アセンブリを呼び出す C# コードを実行すると、純粋な C DLL が呼び出されます。これは、純粋な C DLL 関数を呼び出すオブジェクトがインスタンス化されるとすぐに発生します。

BackingStore は純粋な C です。CPPDemoViewModel は、BackingStore への参照を持つ BackingStore を呼び出す C++/CLI です。

CPPDemoViewModel で定義されたオブジェクトを作成するだけの新しい C# 単体テスト プロジェクトを追加します。C# プロジェクトから CPPDemoViewModel への参照を追加しました。

C++/CLI テスト プロジェクトは、CPPDemoViewModel に ref を追加するだけで問題なく動作するため、言語間を行き来することになります。

.Net 3.5 SP1 で Visual Studio 2008 SP1 を使用しています。Vista x64 でビルドしていますが、プラットフォーム ターゲットが x86 に設定されていることを確認するように注意しています。

これは私が見逃している愚かで明白な何かのように感じますが、私的に解決しようとして時間を無駄にするのはもっと愚かなので、恥ずかしい思いをしてここにいます!

これは、C++/CLI で実装された ViewModel を使用して DLL に保持している膨大な量のレガシー C コードを移植するプロジェクトのテストです。

edit ディレクトリを確認したところ、BackingStore.dll がコピーされていないことが確認できました。

典型的なマルチプロジェクト ソリューションで作成された標準の一意のプロジェクト フォルダーがあります。

WPFViewModelInCPP
  バッキングストア
  CPPViewModel
  CPPViewModelTestInCS
    置き場
      デバッグ
  デバッグ

驚いたことに、上位レベルの Debug は、C および C++/CLI プロジェクトで使用される共通のフォルダーのようです。

WPFViewModelInCPP\Debug には、BackingStore.dll、CPPDemoViewModel.dll、CPPViewModelTest.dll、およびそれらに関連付けられた .ilk および .pdb ファイルが含まれています。

WPFViewModelInCPP\CPPViewModelTestInCS\bin\Debug には CPPDemoViewModel と CPPViewModelTestInCS の .dll と .pdb ファイルが含まれていますが、BackingStore は含まれていません。ただし、BackingStore をそのディレクトリに手動でコピーしても、エラーは修正されませんでした。

CPPDemoViewModel にはプロパティCopy Localセットがあり、参照された場合にその DLL をコピーする責任があると思います。C# プロジェクトからピュア C DLLへの参照を追加できません。「バッキング ストアへの参照を追加できませんでした」と表示されるだけです。

問題が 1 つだけなのか 2 つなのかわかりません。

古い形式のコピー ビルド ステップを使用して、BackingStore.dll を特定の C# プロジェクトのディレクトリにコピーできますが、新しい .net モデルではそれが必要ないことを願っていました。

DependencyWalker は、欠落しているファイルが GPSVC.dll であり、セキュリティ設定の問題を示していると示唆しています。これはニシンだと思います。

edit2 BackingStore.dll の手動コピーを実行可能ファイルに隣接させることで、GUI が正常に動作するようになりました。C# テスト プロジェクトには、テスト プロジェクトの実行環境が原因であると思われる問題がまだ残っていますが、今のところ、それがなくても問題ありません。

4

6 に答える 6

12

C および C++ DLL は、実行中の C# アセンブリと同じディレクトリにありますか?

C# アセンブリとその他の DLL がすべて同じフォルダーに配置されるように、プロジェクトの出力設定を変更する必要がある場合があります。

このような場合、私はしばしばDependency Walkerを使用しました。これは、すべての依存関係が実際に見つかることを示すサニティ チェックです。

アプリが実行されたら、実行中のコードでProcess Monitorを試して、参照されている DLL とその場所を確認することもできます。

于 2009-03-15T04:42:55.050 に答える
4

出力設定を変更する以外のGUIの答えは、ビルド前のステップの追加でした。

copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)

テストプロジェクトの答えは、不足しているDLLをtestrunco​​nfigの[Deployment]タブに追加することでした。これを行うには、デフォルトのLocalTestRun.testrunco​​nfig(ソリューションの[ソリューションアイテム]の下に表示されます)を直接編集するか、ソリューションを右クリックして新しいテスト実行構成を追加します。これにより、メインの[テスト]メニューに表示されます。

私を答えに導くためのテスト構成に関するこのSOの質問に対する答えをありがとう。

于 2009-03-17T07:46:24.890 に答える
4

これが発生する理由は、CRT が初期化される前にマネージ コードから DLLMAIN を読み込んでいるためです。マネージ コードがなく、DllMain 通知の影響で直接または間接的に実行される場合があります。(参照: Expert C++/CLI: .Net for Visual C++ Programmers、第 11++ 章)。

または、ネイティブ エントリポイントがまったく定義されていないにもかかわらず、MSVCRT にリンクしています。CLR は /clr で自動的に初期化されます。この詳細は多くの混乱を招くため、考慮に入れる必要があります。混合モードの DLL は、実際には、クラス内のマネージ エントリ ポイントのすべての vtable にホット パッチを適用することにより、CLR を 遅延ロードします。

このトピックには多くのクラスの初期化の問題があり、ローダーのロックと CLR の読み込みの遅延は少しトリッキーな場合があります。グローバルの static を宣言し、#pragma managed/unmanaged を使用せず、ファイルごとに /clr を使用してコードを分離してください。

コードをマネージ コードから分離できず、問題が発生している場合 (これらの手順のいくつかを実行した後)、CLR を自分でホストし、おそらくドメイン マネージャーを作成する努力をすることもできます。ランタイム イベントとブートストラップの完全な「イン ザ ループ」。

これがまさに理由です。検索パスや初期化とは何の関係もありません。残念ながら、Fusion ログ ビューアーはそれほど役に立ちません (これは、依存関係ウォーカーではなく、.NET CLR アセンブリ バインディングの問題を探す通常の場所です)。

静的にリンクすることも、これとは何の関係もありません。混合モードの C++/CLI アプリケーションを静的にリンクすることはできません。

  1. DLLMAIN 関数を単独でファイルに配置します。
  2. このファイルのビルド オプションに/CLRが設定されていないことを確認します (ファイルビルド オプション) 。
  3. /MD または /MDd とのリンク、およびリンクするすべての依存関係がまったく同じ CRT を使用していることを確認してください。
  4. /DEFAULTLIB および /INCLUDE に対するリンカーの設定を評価して、考えられる参照の問題を特定します。コードでプロトタイプを宣言し、/INCLUDE を使用してデフォルトのライブラリ リンク解決をオーバーライドできます。

頑張ってください、その本もチェックしてください。とても良いです。

于 2009-05-19T05:33:20.110 に答える
2

ターゲット システムに正しい MS Visual C ランタイムがあること、およびデバッグ ランタイムを使用して誤って C dll をビルドしていないことを確認してください。

于 2009-03-15T06:10:15.713 に答える
1

これは興味深いジレンマです。C# からネイティブ .DLL を呼び出した後、C++/CLI からネイティブ .DLL をロードする際に問題が発生したという話は聞いたことがありません。@Daniel Lが示唆したように問題があり、.DLLがアセンブリローダーが見つけられるパスにないだけだと思います。

ダニエルの提案がうまくいかない場合は、可能であれば、ネイティブ C コードを C++/CLI プログラムに静的にリンクすることをお勧めします。.DLL は C++/CLI の .DLL に完全に吸収されるため、問題は確実に解決されます。

于 2009-03-15T05:03:40.117 に答える
0

64 ビット Vista への切り替えでも同じ問題が発生しました。私たちのアプリケーションは、アプリケーションのターゲット ビルドを混乱させる Win32 DLL を呼び出していました。それを解決するために、次のことを行いました。

  1. プロジェクトのプロパティに移動します。
  2. [ビルド] タブを選択します。
  3. 「プラットフォーム ターゲット:」オプションを x86 に変更します。
  4. アプリケーションを再構築します。

アプリケーションを再実行すると、機能しました。

于 2009-07-14T15:47:10.823 に答える