web-dev-qa-db-ja.com

AnyCPUテストアセンブリがx64プロダクションアセンブリからのインターフェイスを実装するとBadImageFormatExceptionが発生する

X64アセンブリを参照するAnyCPUアセンブリでmstestを実行すると、BadImageFormatExceptionが発生するというシナリオにヒットしたようです。

この問題は、AnyCPUTestingx64Production.dllテストアセンブリによってx64Production.dllのインターフェイスが実装されている場合(使用されていない場合でも)に発生します。

Unable to load the test container 'D:\AnyCPUTestingx64Production.dll' 
or one of its dependencies. error details:
System.BadImageFormatException: 
    Could not load file or Assembly 'x64Production, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.
  • mstestはWindows 7 64ビットで実行されています
  • テストアセンブリはAnyCPUとしてビルドされ、64ビットホスト上の64ビットで実行されます(概要 ここ )。
  • testsettingsファイルは<Execution hostProcessPlatform = "MSIL" />を指定します
  • peverifyとcorflagsは何も興味深いものを明らかにしません
  • これはおもちゃのソリューションですぐに再現できます。つまり、
    • x64Production
      • 他のアセンブリを参照しない
      • 空のパブリックインターフェイスIExampleInterfaceのみが含まれます
      • <PlatformTarget>がx64に設定されている
    • AnyCPUTestingx64Production
      • x64Production.dllのみを参照します(つまり、この問題はMicrosoft.VisualStudio.QualityTools.UnitTestFrameworkへの参照がなくても存在します)
      • x64Production.IExampleInterfaceの空の実装のみが含まれます
      • <PlatformTarget>がx64に設定されている
  • nunitはテストアセンブリをロードして実行できます(すべてのテスト属性を変換したら)
    • しかし、より大きな問題(膨大な数のプロジェクトファイルが関係する)に対する適切な短期的な解決策ではありません。
  • プロジェクトが3.5と4.0のどちらを対象としても同じ問題が発生します
  • vS2008またはVS2010 c#コンパイラを使用しても同じ問題が発生します
  • vS2010のmstestを使用しても、Test Agentを使用しても、同じ問題が発生します。
  • anyCPUTestingx64Productionの読み込み中に失敗するのはmstestです。つまり、間違ったQTAgentでアセンブリを読み込もうとしても問題はありません(プロセスモニターに何も表示されず、QTAgent32.exeの名前を変更しても効果はありません)。
    *** Assembly Binder Log Entry  (09/02/2012 @ 09:44:26) ***

    The operation failed.
    Bind result: hr = 0x8007000b. An attempt was made to load a program with an incorrect format.

    Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
    Running under executable  C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe
    --- A detailed error log follows. 

    === Pre-bind state information ===
    LOG: User = David
    LOG: DisplayName = x64Production, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
     (Fully-specified)
    LOG: Appbase = file:///D:/
    LOG: Initial PrivatePath = NULL
    LOG: Dynamic Base = NULL
    LOG: Cache Base = NULL
    LOG: AppName = MSTest.exe
    Calling Assembly : AnyCPUTestingx64Production, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
    ===
    LOG: This bind starts in default load context.
    LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe.Config
    LOG: Using Host configuration file: 
    LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
    LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based Assembly bind).
    LOG: Attempting download of new URL file:///D:/x64Production.DLL.
    LOG: Assembly download was successful. Attempting setup of file: D:\x64Production.dll
    LOG: Entering run-from-source setup phase.
    LOG: Assembly Name is: x64Production, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    ERR: Failed to complete setup of Assembly (hr = 0x8007000b). Probing terminated.

これがVS2010 mstestで単にサポートされていないかどうかを他の誰かが確認しましたか?

25
David

これを読むと、MSTest.exeは32ビットです。

12
Joshua

私は同様の問題の解決策を探してここに来ました。私が見つけた解決策が誰かを助ける場合に備えて、この回答を投稿する。これは私のためにそれをVisual Studio(2012)で解決しました:

新しいアイテムの追加->テスト設定 Add Test Setting Item テスト設定を変更する Run test in 64 bit process デフォルトでは、これは"32ビットプロセスでテストを強制的に実行する"に設定されています。

メニューから:テスト->テスト設定->テスト設定ファイルの選択->作成したテスト設定ファイルを選択します。

次にテストを実行します。

33
Anupam

現在、Visual Studio 2013では(少なくとも2012年は試していません)、何もする必要はありませんでした。ただし、[テスト]-> [テスト設定]-> [既定のプロセッサアーキテクチャ]-> [x64]を選択します。テスト設定ファイルを使用して同じ結果を得ることができます。他の回答やWebでのさまざまな投稿で見る必要のある古いクルージュはありません。私のものはx64を使用する必要があるため、設定が間違っている場合に通知するために、これらのテストケースも追加しました。

    [TestMethod]
    public void Running_64Bit_OS()
    {
        // It was determined to run only in 64 bits.
        bool is64BitOS = System.Environment.Is64BitOperatingSystem;
        Assert.AreEqual(is64BitOS, true);
    }

    [TestMethod]
    public void Running_64Bit_Process()
    {
        // We have a requirement that one of the unmanaged DLL is built for 64 bits.
        // If you are running MS Test in Visual Studio 2013 and this
        // is failing, go to Test->Test Settings->Default Processor Architecture and
        // chose x64, then run the tests again.  This is not the only method.  You
        // could also use a test settings file.
        bool is64BitProcess = System.Environment.Is64BitProcess;
        Assert.AreEqual(is64BitProcess, true);
    }
18
JustTrying

また、メニューの[テスト]-> [テスト設定]-> [デフォルトのプロセッサアーキテクチャ]-> [X64]に移動することもできます。うまくいくかもしれません。

15
user2545071

私の場合、x86またはx64プラットフォーム、テスト構成設定、またはプロジェクトの.NETバージョンとは何の関係もないようです。ところで、私は「署名が間違っている」ということについても言及したBadImageFormatExceptionエラー。

問題は、Moqを使用するときに、モックしようとしているオブジェクトに依存するクラス/インターフェースのユニットテストプロジェクトに不足している参照を追加する必要があることでした。テストしているプロジェクトの参照を調べて、モックしているオブジェクトに関連する、欠落している可能性のあるアセンブリを把握します。

http://vibrantcode.com/2012/05/18/badimageformatexception-the-signature-is-incorrect/

3
hagensoft

ReSharperがインストールされている場合は、以下を参照してください link

基本的に、他の回答に示されているようにソリューションにテスト設定ファイルを作成し、MsTestのReSharperオプションを更新して同じ設定ファイルを指すようにする必要があります。

私はVisual Studio 2013 Update 4とResharper 8.2を使用してこの問題を見つけました。

2
wonster

MSTestをセットアップして64ビットアセンブリをテストする方法

この質問では、他の回答者から提供された.testsettings情報に加えて、この回答はVisual Studio 2015とVisual Studio 2017の初期バージョンのいくつかの癖をカバーしています。この修正はVisual Studio 2013でも機能する可能性がありますが、そのためにテストできるマシン。

1. .testsettingsファイルを追加する

Solution(単体テストプロジェクトではない)を右クリックし、[テスト設定]カテゴリに.testsettingsファイルを追加します。好きな名前を付けることができます。

Add test settings window screenshot


2. 64ビットプロセスを使用するように.testsettingsファイルを構成する

表示される[テスト設定]ウィザードで、カスタマイズする必要があるのは[ホスト]タブで、[32ビットまたは64ビットプロセスでテストを実行]を[64ビットで64ビットプロセスでテストを実行]に設定することだけです。機械"。ここにいる間は、デフォルト設定を見直して、意​​味があることを確認することをお勧めします。 「適用」をクリックし、完了したら「閉じる」をクリックします。

Test settings configuration window, showing where to set it to 64 bit

これで、.testsettingsファイルがソリューションエクスプローラーに表示されます。

Image showing the test settings file in the solution Explorer


Visual Studio 2015のバグの追加の回避策

  • Visual Studio 2017(バージョン15.3.3コミュニティを使用してテスト済み)では、手順3と4が不要になったようです。これらの手順は、古いバージョンのVisual Studioを使用している場合や、動作を再現する方法がまだある場合のために、ここに残しておきます。

  • Visual Studio 2015では、テスト->テスト設定->デフォルトプロセッサアーキテクチャ-> x64でデフォルトプロセッサアーキテクチャを設定しただけの場合、Visual Studioは設定を忘れます( このバグレポートを参照 )。これはVisual Studio 2015 Professional Update 3でテストされています。

  • 私が読んだことから、CPUアーキテクチャの記憶に関しては、Visual Studio 2013にはVisual Studio 2015と同様のバグがあります。私はこれをVisual Studio 2013でテストしていません(私は持っていません)が、試してみる価値があるかもしれません。

3. .runsettingsファイルを追加して、テストを永続的に64ビットに設定します

メモ帳(または任意のXMLファイルエディター)を開き、これに貼り付けます。

<?xml version="1.0" encoding="utf-8"?>  
<RunSettings>  
    <!-- Configurations that affect the Test Framework -->  
    <RunConfiguration>  
        <!-- [x86] | x64 -->  
        <TargetPlatform>x64</TargetPlatform> 
    </RunConfiguration> 
</RunSettings> 

次に、ファイルを保存し、DemoTest.runsettingsとして、DemoTest.testsettingsと共にソリューションのディレクトリに保存しました。

  • このファイルの詳細については、「 。runsettingsファイルを使用してユニットテストを構成する 」を参照してください。

  • 注:このエントリだけを含む.runsettingsファイルを作成しても安全です。理由は...

    すべての値にはデフォルトがあるため、ファイルの各要素はオプションです。

  • ソリューションに.runsettingsファイルを追加することをお勧めします。これにより、開発者がソリューションエクスプローラーでファイルを確認できるようになりますが、これは機能には影響しません。


4. .runsettingsファイルをロードします

メニューバーで、[テスト]-> [テスト設定]-> [テスト設定ファイルの選択]をクリックします。

Image showing how to load a test settings file using the Test menu

runsettingsファイルを選択します。 testsettingsファイルではありません。


これで問題なくテストを実行できるはずです。

image showing that the tests are okay

MSTestの制限

  • MSTestはAny CPUとしてコンパイルされた単体テストプロジェクトでのみ機能することに注意してください。 x64テストプロジェクトでは、テストエクスプローラーにテストは表示されません。

  • テストするアセンブリはx64にすることができますが、単体テストライブラリ自体は任意のCPUでなければなりません。

Configuration manager showing that the unit test library must be built as Any CPU

1
jrh

次の このブログ投稿 に続いて、VSコマンドプロンプト(CorFlags.exeがPATHにある)から実行すると、私のおもちゃのソリューションでテストが実行されます。

@echo off
REM remove the 32Bit flag, forcing the executable to be 64-bit when run on a 64 bit os.
REM Expect the following output:
REM "
REM corflags : warning CF011 : The specified file is strong name signed.  Using /Force will invalidate the signature of this image and will require the Assembly to be resigned.
REM "
CorFlags.exe "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe" /32BIT- /Force

REM skip the strong name verification, because the 32-bit flag was modified 
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\MSTest,b03f5f7f11d50a3a /f

REM copy over registry keys to the 64-bit shadow registry.
REM Without the "{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\Extensions" subkey, mstest will output
REM "
REM File extension specified '.dll' is not a valid test extension.
REM "
reg copy HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\EnterpriseTools\QualityTools\TestTypes HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\EnterpriseTools\QualityTools\TestTypes /s /f

これが実際のプロダクションコードにどのように対抗するかは、まだ不明です。

1
David

@Anupamソリューションに加えて、VS2013ではTEST> Test Settings> Default Processor Architectureに移動して、X86X64の間で変更できます。テストプラットフォームを指定するためだけにファイルが必要ないことを除いて、テスト設定ファイルを選択するのとほとんど同じです。

0
fernacolo

MSTestに切り替えることで問題を回避できると指摘したため、Resharperのヒントをありがとう。 Resharperを動作させることができませんでした。 64ビットサードパーティのテスト64ビットDLL(モックしているだけでも(ロードする必要があります))64ビットモードのMsTestでのみ動作するように見えます。MSTestのResharperオプションは " [このテスト実行構成を使用]には、ドロップダウンオプションとして[デフォルト]しかなく、[編集]はグレー表示されます。他の設定[メタデータファイルで指定されたテスト実行構成を使用]も機能せず、これは、このメタデータの内容または場所がわかっていることを前提としています。上記の環境変数Is64BitProcessで証明されているように、Resharperは64ビットモードで実行されません(VS 2013 Update 4、Resharper 8.2)。

0
Wray Smallwood