【问题标题】:BadImageFormatException when AnyCPU test assembly implements interface from x64 production assembly当 AnyCPU 测试程序集从 x64 生产程序集实现接口时出现 BadImageFormatException
【发布时间】:2020-10-29 00:59:20
【问题描述】:

我似乎遇到了这样一种情况,当我在引用 x64 程序集的 AnyCPU 程序集上运行 mstest 时,我得到了 BadImageFormatException。

当 x64Production.dll 中的接口由 AnyCPUTestingx64Production.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 位运行(如here 所述)
  • testsettings 文件指定
  • peverify 和 corflags 没有发现任何有趣的东西
  • 这很容易在玩具解决方案中重现,即
    • x64生产
      • 不引用其他程序集
      • 仅包含一个空的公共接口 IExampleInterface
      • 已将 设置为 x64
    • AnyCPUTestingx64Production
      • 仅引用 x64Production.dll(即即使不引用 Microsoft.VisualStudio.QualityTools.UnitTestFramework 也会出现此问题)
      • 仅包含 x64Production.IExampleInterface 的空实现
      • 已将 设置为 x64
  • nunit 可以加载和运行测试程序集(一旦我转换了所有测试属性)
    • 但对于较大的问题(涉及大量项目文件)不是一个好的短期解决方案
  • 无论项目的目标是 3.5 还是 4.0,都会出现同样的问题
  • 无论使用 VS2008 还是 VS2010 c# 编译器都会出现相同的问题
  • 无论是使用来自 VS2010 的 mstest 还是使用测试代理,都会出现同样的问题
  • mstest 在加载 AnyCPUTestingx64Production 时失败 - 即尝试在错误的 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 中是否完全不受支持?

【问题讨论】:

  • 构建一个针对 x64 的 DLL 毫无意义,始终以 AnyCPU 为目标。该设置仅对 EXE 项目重要。 Mstest 在 32 位模式下运行。
  • @Hans,我的印象是 (1,2,3),如果项目最终调用非托管 DLL本身64位。您能否就此提供任何进一步的理由?
  • 请考虑更改您接受的答案。现在有多种方法可以将测试平台配置为在 64 位以上运行。

标签: c# visual-studio-2010 mstest 64-bit


【解决方案1】:

我来这里是为了寻找类似问题的解决方案。发布此答案以防万一我找到的解决方案对其他人有帮助。 这在 Visual Studio (2012) 中为我解决了这个问题:

添加新项目 -> 测试设置 更改测试设置 默认设置为“强制测试在 32 位进程中运行”

从菜单中: 测试 -> 测试设置 -> 选择测试设置文件 -> 选择您创建的测试设置文件。

现在运行测试。

【讨论】:

  • 请注意,这个解决方案在 VS2010 中不可用,这就是这个问题的含义。
  • 在 VS2017 Enterprise 中也有 ;)
  • 也适用于 VS 2019 Pro。有例外,但在创建新的测试设置文件时,上述选项已经是默认选项。仍然需要创建我自己的...谢谢!
【解决方案2】:

现在使用 Visual Studio 2013(至少在 2012 年没有尝试过),我无需执行任何操作,只需选择测试->测试设置->默认处理器体系结构->x64。也可以使用测试设置文件来达到同样的效果。您在其他答案和网络上的各种帖子中看到的那些旧知识都不是必需的。由于我的东西必须使用 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);
    }

【讨论】:

  • VS2012也有这个功能
  • 自 VS2013 Update 4 起仍然有效。在尝试测试旧项目时一度非常困惑,这立即修复了它。
  • 只是为了挑剔,你的断言应该有相反的参数,或者更好地使用 Assert.IsTrue。
【解决方案3】:

另外,您可以进入菜单测试->测试设置->默认处理器架构->X64。它可能会起作用。

【讨论】:

  • 即使您选择的测试设置文件声明了处理器位数,这也是必需的。
【解决方案4】:

通过阅读,MSTest.exe 是 32 位的。

【讨论】:

  • 你是对的。没有找到任何资源表明这是不可能的,我一定是乐观地误解了我正在阅读的内容。 "Visual Studio Team Test Load Agent Goes 64 Bit!") 声明“我们实际上只支持针对“任何 CPU”或“x86”平台的测试程序集。掌心。
  • 而且由于您要加载本机 x64 DLL,因此更改为 Any CPU 实际上并没有帮助。关心进程外 COM 或其他一些疯狂的想法?我没有。
  • 好吧,对我来说可悲的解决方案是简单地通过控制台应用程序进行测试。创建您的测试方法并修改您的Program() 方法以启动您需要运行的方法。就像在 2005 年重新开发一样!
  • Anupam 的以下解决方案完美运行,获得了 20 多个支持。
  • @ragche:请注意,Anupam 的解决方案适用于 VS2012,但 OP 有 VS2010,这并不适用。
【解决方案5】:

就我而言,它似乎与 x86 或 x64 平台或测试配置设置或项目的 .NET 版本无关。顺便说一句,我得到的 BadImageFormatException 错误还提到了一些关于“签名不正确”的内容。

问题在于,在使用 Moq 时,我们需要为依赖于我们尝试模拟的对象的类/接口添加对单元测试项目的缺失引用。查看您正在测试的项目的引用,以了解您可能缺少哪些与您正在模拟的对象相关的程序集。

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

【讨论】:

    【解决方案6】:

    如果您安装了 ReSharper,请参考以下link

    基本上,您需要在解决方案中创建一个测试设置文件,如其他答案所示,然后更新 MsTest 的 ReSharper 选项以指向相同的设置文件。

    我使用 Visual Studio 2013 Update 4 和 Resharper 8.2 发现了这个问题。

    【讨论】:

      【解决方案7】:

      在关注this blog post 之后,从 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
      

      这将如何与真正的生产代码相比还有待观察。

      【讨论】:

      • 针对实际测试:BadImageFormatException。我现在要停止鞭打这匹死马了。
      • 我想知道我们是否应该使用 mstest 或 nunit。根据您的经验,您是否认为 mstest 不适用于 64 位?谢谢!!
      • @AnneTheAgile,根据我的经验,它不适用于 64 位生产代码。看起来虽然测试可以在 64 位平台上运行,但它们无法测试 64 位代码。不过,我非常想反驳这一点!
      【解决方案8】:

      除了@Anupam 解决方案,在VS2013 上,您可以转到TEST > Test Settings > Default Processor Architecture 并在X86X64 之间切换强>。与选择测试设置文件几乎相同,只是您不需要该文件来仅指定测试平台。

      【讨论】:

      • 在 VS2017 上也为我工作过!
      【解决方案9】:

      如何设置 MSTest 以测试 64 位程序集

      除了这个问题的其他回答者提供的 .testsettings 信息之外,这个答案涵盖了 Visual Studio 2015 和 Visual Studio 2017 早期版本的一些怪癖,这个修复可能也适用于 Visual Studio 2013,但我不'没有可用于测试的机器。

      1。添加 .testsettings 文件

      右键单击Solution(不是单元测试项目),然后在Test Settings 类别下,添加一个.testsettings 文件。可以任意命名。


      2。将 .testsettings 文件配置为使用 64 位进程

      在出现的“测试设置”向导中,您唯一需要自定义的是在“主机”选项卡下,将“在 32 位或 64 位进程中运行测试”设置为“在 64 位进程中运行测试”在 64 位机器上”。当您在这里时,最好查看默认设置以确保它们有意义。单击应用,完成后单击关闭。

      现在您的 .testsettings 文件将显示在解决方案资源管理器中。


      针对 Visual Studio 2015 中的错误的额外解决方法

      • 似乎 Visual Studio 2017(使用版本 15.3.3 社区测试)已使步骤 3 和 4 变得不必要。我会将这些步骤留给那些使用旧版本 Visual Studio 的人,或者以防万一仍有重现该行为的方法。

      • 在 Visual Studio 2015 中,如果您只是通过测试 -> 测试设置 -> 默认处理器架构 -> x64 设置默认处理器架构,Visual Studio 将忘记您的设置 (see this bug report)。这已在 Visual Studio 2015 Professional Update 3 中进行了测试。

      • 根据我的阅读,Visual Studio 2013 在记忆 CPU 架构方面存在与 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。

      • 有关此文件的更多信息,请参阅Configure unit tests by using a .runsettings file

      • 注意:只有这个条目的 .runsettings 文件是安全的,因为...

        文件的每个元素都是可选的,因为每个值都有一个默认值。

      • 我建议将您的 .runsettings 文件添加到您的解决方案中,以便开发人员可以在解决方案资源管理器中看到它,尽管这不会以任何方式影响功能。


      4。加载你的 .runsettings 文件

      在菜单栏中,点击测试 -> 测试设置 -> 选择测试设置文件

      选择您的 runsettings 文件。不是您的测试设置文件。


      现在您应该能够毫无问题地运行测试了。

      MSTest 限制

      • 请注意,MSTest 仅适用于编译为 Any CPU 的单元测试项目。 x64 测试项目不会在测试资源管理器下显示任何测试。

      • 要测试的程序集可以是 x64,但单元测试库本身必须是 Any CPU。

      【讨论】:

      • 我注意到,出于某种原因,如果您不运行多个 Visual Studio 实例,VS 2015 修复似乎效果最佳。
      【解决方案10】:

      感谢有关 Resharper 的提示,因为它指出可以通过切换到 MSTest 来避免该问题。我无法让 Resharper 工作。测试 64 位第三方 64 位 DLL,即使您只是在模拟它(仍然必须加载它),似乎也只能在 64 位模式下与 MsTest 一起使用。 MSTest 的 Resharper 选项“使用此测试运行配置”只有“默认”作为下拉选项,“编辑”显示为灰色。另一个设置“使用元数据文件中指定的测试运行配置”也不起作用,这假设人们知道这个元数据文件是什么或在哪里。正如上述环境变量 Is64BitProcess 所证明的,Resharper 不会在 64 位模式下运行。 (VS 2013 更新 4,Resharper 8.2)

      【讨论】:

        【解决方案11】:

        错误的原因之一是 如果您在解决方案中引用另一个项目,请右键单击引用的项目, 选择应用程序选项卡,检查输出类型。如果输出类型是控制台应用程序切换到类库然后尝试运行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-05
          • 1970-01-01
          • 2017-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多