8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

.NET 5.0のC#プロジェクトからC++/CLIのDLLを使う際に起きたSystem.BadImageFormatException(間違ったフォーマットのプログラムを読み込もうとしました)の解決方法

Last updated at Posted at 2021-05-06

はじめに

手元にある太古のCで書かれたWin32なスタティック ライブラリを、Visual Studio 2019でASP.NET 5.0を使ってWeb API化しようと思い立ち挑戦したところ、スタティック ライブラリをラップした C++/CLI のアセンブリを使うところで

System.BadImageFormatException: Could not load file or assembly 'HogeWrapper, Version=1.0.7796.41445, Culture=neutral, PublicKeyToken=null'. 間違ったフォーマットのプログラムを読み込もうとしました。

のエラーでハマってしまったため、解決方法をメモしておきます。

背景

10年以上前のVisual StudioでビルドされたWin32(x86)のスタティック ライブラリ hoge.libを.Net 5.0で使うために、まず C++/CLI でラッパーのクラスライブラリのDLLHogeWrapper.dllを作成しました。元のLIBが64bit対応していないので、このDLLも32bit縛りです。

次にDLL単独の動作確認のため、同じソリューション内に.Net 5.0 C#のコンソール アプリのプロジェクトを作って、ソリューション内のDLLのプロジェクトと依存関係を結んで実行したところ、うまく使うことができました。

そして最後に、別のソリューションでASP.NET 5.0 C#のWeb APIプロジェクトを作り、HogeWrapper.dllを参照設定しました。これで間接的にhoge.libの機能が呼び出せるようになります。ビルドまでは順調でした。

しかし、実行時にハマりました。以下、Debug実行時の出力ウィンドウの途中部分なのですが、せっかくロードしたHogeWrapper.dllがすぐにアンロードされてしまい、例外System.BadImageFormatExceptionがスローされてしまいます。

'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' が読み込まれました。シンボルが読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\msvcp140d.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\ucrtbased.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\vcruntime140d.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\vcruntime140d.dll' がアンロードされました
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\ucrtbased.dll' がアンロードされました
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\msvcp140d.dll' がアンロードされました
'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' がアンロードされました
'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' が読み込まれました。シンボルが読み込まれました。
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: HRException (メモリの場所 0x065ACAD0)。
'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' がアンロードされました
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x00000000)。
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: EEFileLoadException (メモリの場所 0x065AD048)。
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x00000000)。
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x00000000)。
0x7519C602 で例外がスローされました (Hoge.exe 内): Microsoft C++ の例外: [rethrow] (メモリの場所 0x00000000)。
'Hoge.exe' (Win32): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\Microsoft.DiaSymReader.Native.x86.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Diagnostics.StackTrace.dll' が読み込まれました。
'Hoge.exe' (CoreCLR: clrhost): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Diagnostics.StackTrace.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
'Hoge.exe' (Win32): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Reflection.Metadata.dll' が読み込まれました。
'Hoge.exe' (CoreCLR: clrhost): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Reflection.Metadata.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
'Hoge.exe' (Win32): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Collections.Immutable.dll' が読み込まれました。
'Hoge.exe' (CoreCLR: clrhost): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.Collections.Immutable.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
'Hoge.exe' (Win32): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.IO.MemoryMappedFiles.dll' が読み込まれました。
'Hoge.exe' (CoreCLR: clrhost): 'C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\5.0.5\System.IO.MemoryMappedFiles.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.BadImageFormatException: Could not load file or assembly 'HogeWrapper, Version=1.0.7796.41445, Culture=neutral, PublicKeyToken=null'. 間違ったフォーマットのプログラムを読み込もうとしました。
File name: 'HogeWrapper, Version=1.0.7796.41445, Culture=neutral, PublicKeyToken=null'
   at Hoge.Controllers.KeywordItemsController.Get(String data)
   at lambda_method2(Closure , Object , Object[] )

解決方法

このSystem.BadImageFormatExceptionは、x86(Win32)とx64を混在させた時などに起こるそうなのですが、ASP.NET 5.0のWeb API側もきちんとx86に縛っていて混在はしていません。

ググってもうまく日本語の情報が見つからず、仕方がないので苦手な英語のサイトを追い始めたところ、Stack OverflowでそのものズバリのQAがありました。

Bad image format when running managed C++/CLI assembly in .NET Core 3.1

これは .NET Core 3.1時代のものですが .NET 5.0も同様でした。C++/CLIのDLLを使う場合、DLLだけ持ってきてもダメで、同じ位置に出力されるIjwhost.dllもDLLと同じ位置に持っていかないとダメだそうです。今回 .NET Core系のC++/CLIを初めて使ったので、この辺りの常識を全く知りませんでした。

DLLはC:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dllにあるので、同じ位置にIjwhost.dllを持っていったところ、無事にエラーが解消しました。以下、正常時の出力ウィンドウの抜粋です。DLLと同じ位置に置いたIjwhost.dllが読み込まれているのがわかります。

'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' が読み込まれました。シンボルが読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\vcruntime140d.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\ucrtbased.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Windows\SysWOW64\msvcp140d.dll' が読み込まれました。
'Hoge.exe' (Win32): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\Ijwhost.dll' が読み込まれました。
'Hoge.exe' (CoreCLR: clrhost): 'C:\Users\Segavvy\source\repos\Hoge\Hoge\bin\x86\Debug\net5.0\HogeWrapper.dll' が読み込まれました。シンボルが読み込まれました。

なお、最初にHoge.dllの動作確認を簡単なC#のコンソール アプリで実施した時につまずかなかったのは、同一ソリューション内にDLLのプロジェクトも入れて、プロジェクトの依存関係を結んで使ったためです。これならDLLの位置にIjwhost.dllもある形が維持されます。

別ソリューションからDLLの参照設定で使う場合は、今回のような注意が必要です。Debug/Releaseの切り替えなども考えると、手元にプロジェクト ファイルがある場合は同一ソリューションに入れてしまうのが正解みたいです。

おわりに

.NET Core系を初めて使っているので、誤りがあるかも知れません。正しい参照設定の方法がありそうな気もします。何かわかったら更新します。識者の方のアドバイスもお待ちしております。

(参考)

.NetCore3.1向けC++/CLIを軽く試した感想

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?