Vistax64上のVisualStudio2008でWCFサービスライブラリを作成することは、x86DLLを参照するときに面倒です。32ビットDLLを呼び出すサービスは、64ビットOSで実行するためにx86のプラットフォームターゲットを持っている必要があります。これを行うと、サービスをデバッグしようとしたときにWcfSvcHostがBadImageFormatExceptionをスローします。MS接続に関するバグレポートがあります。私が使用した回避策は、WcfSvcHostを32ビットとしてコアフラグを立てることでした。
マニフェスト問題
私が遭遇した主な問題は、このサードパーティのネイティブ32ビットDLLが特定のWCFホストを使用してロードできないことです。サードパーティのDLLを使用するサービス操作が呼び出されると、次のエラーが発生します。
System.TypeInitializationException:''の型初期化子が例外をスローしました。
.ModuleLoadExceptionHandlerException:C++モジュールのロードに失敗する原因となったプライマリ例外の後にネストされた例外が発生しました。
System.BadImageFormatException:モジュールにアセンブリマニフェストが含まれていることが期待されていました。(HRESULTからの例外:0x80131018)
NestedException:
ハンドルが無効です。(HRESULTからの例外:0x80070006(E_HANDLE))
この例外は、WcfSvcHostの起動時に発生するのではなく、32ビットDLLを参照するサービス操作が呼び出されたときに発生します。非常に興味深いのは、コンソールアプリで同じapp.configを使用してこの同じサービスをホストすることには例外がなく、完全に機能することです。
using (ServiceHost host = new ServiceHost (typeof (MsgBrokerService))) {
host.Open ();
Console.WriteLine ("running");
Console.ReadLine ();
この例外は、次の直後に発生します。
'WcfSvcHost.exe'(管理対象):ロード済み'C:\ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll '
この場合も、コンソールアプリには例外がなく、同じDLLが読み込まれます。
'ConsoleApp.vshost.exe'(管理対象):ロード済み'C:\ Windows \ WinSxS \ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.3053_ none_d08d7bba442a9b36 \ msvcm80.dll '
Microsoft製品サポートからの回答を参照してください。
更新#1:コンソールアプリケーションとWcfSvcHost.exeホストプロセスの両方が、同じセッションとログインユーザー(私)の下で実行されます。WcfSvcHost.exeをサービスのディレクトリにコピーし、手動で起動して同じ結果が得られました。また、Windowsイベントログで追加情報を確認し、sxstraceを使用しましたが、何もログに記録されませんでした。
Process Explorerを実行して、2つのプロセス間で次のことが同じであることを確認しました。
- 画像:32ビット
- カレントディレクトリ
- ユーザー/SID
- セッション
- セキュリティ(グループが拒否され、特権が無効になります)
プロセスモニターを実行し、シンボルを構成すると、WcfSvcHostが次のレジストリとファイルを検索しますが、コンソールホストは検索しません。Process Monitorは大量のデータをログに記録しますが、何を探しているのかわかりません:(。
HKLM \ SOFTWARE \ Microsoft \ Fusion \ PublisherPolicy \ Default \ policy.8.0.msvcm80__b03f5f7f11d50a3a C:\ Windows \ assembly \ GAC_32 \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a C:\ Windows \ assembly \ GAC_MSIL \ msvc Windows \ assembly \ GAC \ msvcm80 \ 8.0.50727.3053__b03f5f7f11d50a3a
更新#2:これと同じ例外は、サービスがIIS 6 / WindowsServer2003の運用環境でホストされている場合に発生します。
アップデート#3:サードパーティの32ビット.NETアセンブリはStreamBase APIです:
- sbclient.dll(管理対象)
- monitor.netmodule(管理対象)
- dotnetapi.dll(管理されていない)
- pthreads-vc8.dll(管理されていない)
アップデート#4:成功せずにマニフェストを追加:
- dotnetapi.dllとpthreads-vc8.dllにRT_MANIFESTがあることを確認しました。sbclient.dll.NETアセンブリにマニフェストがありませんでした
- GACからsbclient.dllを削除しました
- 検証スキップ用にsbclient.dllを登録しました
- mt.exeを介してsbclient.dllとmonitor.netmoduleの両方にマニフェストを追加しました
- 検証済みのマニフェストが追加され、テスト中に予期されたファイルが読み込まれたことを確認しました(Visual Studio-デバッグモジュールウィンドウを介して)
- 同じBadImageFormatExceptionがBackgroundWorker.OnDoWork()の下でスローされ、呼び出しスタックはdotnetapi.dll ... DefaultDomain.Initalize()への呼び出しを示します。
msvcm80.dllにマニフェストがないことを確認しました。これが、マニフェストがないロードされた唯一のファイルだと思います:)
面白い発見
リフレクターにmonitor.netmoduleをロードすると、次のように表示されます。
'monitor.netmodule'には、アセンブリマニフェストが含まれていません。
エラーが表示されても、Reflectorはマネージコードを分解できます。