web-dev-qa-db-fra.com

BadImageFormatException lorsque AnyCPU test Assembly implémente une interface à partir d'un assemblage de production x64

Il semble que je sois tombé sur un scénario où, lorsque je lance mstest sur un assembly AnyCPU qui fait référence à un assembly x64, j'obtiens une BadImageFormatException.

Le problème se produit lorsqu'une interface dans x64Production.dll est implémentée (même si elle n'est pas utilisée) par le test 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 s'exécute sur Windows 7 64 bits
  • l'assembly de test est construit en tant que AnyCPU pour le faire fonctionner en 64 bits sur un hôte 64 bits (comme indiqué ici )
  • le fichier testsettings spécifie <Execution hostProcessPlatform = "MSIL" />
  • peverify et corflags ne révèlent rien d'intéressant
  • ceci est facilement reproductible dans une solution jouet, c'est-à-dire où
    • x64Production
      • ne fait référence à aucun autre assemblage
      • inclut uniquement une interface publique vide IExampleInterface
      • <PlatformTarget> a-t-il la valeur x64?
    • AnyCPUTestingx64Production
      • référence uniquement x64Production.dll (c.-à-d. que ce problème existe même sans référence à Microsoft.VisualStudio.QualityTools.UnitTestFramework)
      • inclut uniquement une implémentation vide de x64Production.IExampleInterface
      • <PlatformTarget> a-t-il la valeur x64? 
  • launité peut charger et exécuter le test Assembly (une fois tous les attributs de test convertis)
    • mais ce n’est pas une bonne solution à court terme au problème plus vaste (qui implique un grand nombre de fichiers de projet)
  • le même problème se pose que les projets ciblent 3.5 ou 4.0
  • les mêmes problèmes se posent si le compilateur VS2008 ou VS2010 c # est utilisé
  • le même problème se pose si mstest de VS2010 ou des agents de test est utilisé
  • c'est mstest qui échoue lors du chargement de AnyCPUTestingx64Production - ce n'est pas un problème pour tenter de charger l'assembly dans le mauvais QTAgent (rien ne s'affiche dans Process Monitor et renommer QTAgent32.exe n'a aucun effet):
    *** 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.

Est-ce que quelqu'un d'autre a vérifié si cela est simplement non pris en charge dans le mstest du VS2010?

23
David

De lire ceci, MSTest.exe est 32 bits.

12
Joshua

Je suis venu ici à la recherche d'une solution à un problème similaire. Afficher cette réponse au cas où la solution trouvée aiderait quelqu'un d'autre. Cela a résolu le problème pour moi dans Visual Studio (2012):

Ajouter un nouvel élément -> Paramètres de test Add Test Setting Item Changer le test Run test in 64 bit process Par défaut, il est défini sur "Forcer l'exécution du test dans un processus 32 bits"

Dans le menu: Test -> Paramètres de test -> Sélectionner le fichier de paramètres de test -> Choisissez le fichier de paramètres de test que vous avez créé.

Maintenant, lancez les tests.

31
Anupam

Maintenant, avec Visual Studio 2013 (du moins, je n'ai pas essayé en 2012), je n'avais rien d'autre à faire que choisir Test-> Paramètres de test-> Architecture du processeur par défaut-> x64. Peut également utiliser le fichier de paramètres de test pour obtenir le même résultat. Aucun de ces vieux kluges nécessaires que vous voyez dans d'autres réponses et diverses publications sur le web. Étant donné que mon matériel doit utiliser x64, j'ai ajouté ces cas de test aussi, juste pour me rappeler si certains réglages sont incorrects.

    [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);
    }
17
JustTrying

Vous pouvez également accéder au menu Test-> Paramètres de test-> Architecture de processeur par défaut-> X64. Cela peut marcher.

12
user2545071

Dans mon cas, cela ne semblait avoir rien à voir avec la plate-forme x86 ou x64, les paramètres de configuration de test ou la version .NET du projet. BTW l'erreur BadImageFormatException J'ai aussi mentionné quelque chose à propos de «la signature est incorrecte».

Le problème était que lors de l'utilisation de Moq, nous devons ajouter des références manquantes au projet de test d'unité pour les classes/interfaces dépendantes de l'objet que nous essayons de simuler. Examinez les références du projet que vous testez pour avoir une idée des assemblages manquants en rapport avec l'objet que vous vous moquez.

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

3
hagensoft

Si vous avez installé ReSharper, référez-vous au suivant link

Pour résumer, vous devez créer un fichier de paramètres de test dans votre solution, comme indiqué dans les autres réponses, puis mettre à jour l'option ReSharper pour que MsTest pointe sur le même fichier de paramètres. 

J'ai rencontré ce problème à l'aide de Visual Studio 2013 Update 4 et Resharper 8.2.

2
wonster

Comment configurer MSTest pour tester un assemblage 64 bits

Outre les informations .testsettings fournies par les autres intervenants sur cette question, cette réponse couvre certaines des bizarreries de Visual Studio 2015 et des premières versions de Visual Studio 2017, ce correctif peut également fonctionner pour Visual Studio 2013, mais je ne l'ai pas déjà. une machine disponible pour tester avec pour cela.

1. Ajouter un fichier .testsettings

Cliquez avec le bouton droit sur Solution (pas le projet de test unitaire), puis sous la catégorie Paramètres de test, ajoutez un fichier .testsettings. On peut nommer tout ce que vous voulez.

 Add test settings window screenshot


2. Configurez le fichier .testsettings pour utiliser un processus 64 bits

Dans l'assistant "Paramètres de test" qui apparaît, la seule chose que vous devez personnaliser se trouve sous l'onglet "Hôtes", définissez l'option "Exécuter les tests dans un processus 32 bits ou 64 bits" sur "Exécuter des tests dans un processus 64 bits sur un processeur 64 bits. machine". Pendant que vous êtes ici, il peut être judicieux de revoir les paramètres par défaut pour s’assurer qu’ils ont un sens. Cliquez sur Appliquer, puis sur Fermer lorsque vous avez terminé.

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

Votre fichier .testsettings apparaîtra maintenant dans l'explorateur de solutions.

 Image showing the test settings file in the solution Explorer


Solution de contournement supplémentaire pour un bogue dans Visual Studio 2015

  • Il semble que Visual Studio 2017 (testé avec la version 15.3.3 Community) ait rendu inutiles les étapes 3 et 4. Je vais laisser ces étapes ici pour ceux d’entre vous qui utilisent des versions antérieures de Visual Studio ou s’il existe encore un moyen de reproduire le problème.

  • Dans Visual Studio 2015, si vous définissez simplement l'architecture de processeur par défaut via Test -> Paramètres de test -> Architecture de processeur par défaut -> x64, Visual Studio oubliera votre paramètre ( voir ce rapport de bogue ). Cela a été testé dans Visual Studio 2015 Professional Update 3.

  • D'après ce que j'ai lu, Visual Studio 2013 présente un bogue similaire à Visual Studio 2015 lorsqu'il s'agit de rappeler l'architecture du processeur. Je n'ai pas testé cela sur Visual Studio 2013 (je ne l'ai pas), mais cela vaut peut-être la peine d'essayer.

3. Ajoutez un fichier .runsettings pour que vos tests soient en permanence en 64 bits.

Ouvrez le bloc-notes (ou l'éditeur de fichier XML de votre choix) et collez-le dans celui-ci.

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

Ensuite, sauvegardez le fichier, je l'ai sauvegardé sous DemoTest.runsettings dans le répertoire de ma solution, à côté de DemoTest.testsettings.

  • Veuillez consulter Configurez les tests unitaires à l'aide d'un fichier .runsettings pour plus d'informations sur ce fichier.

  • Remarque: il est prudent d’avoir un fichier .runsettings uniquement avec cette entrée, car ...

    Chaque élément du fichier est facultatif, car chaque valeur a une valeur par défaut.

  • Je recommande d'ajouter votre fichier .runsettings à votre solution, afin que les développeurs puissent le voir dans l'explorateur de solutions, même si cela n'a aucune incidence sur les fonctionnalités.


4. Chargez votre fichier .runsettings

Dans la barre de menus, cliquez sur Test -> Paramètres de test -> Sélectionner le fichier de paramètres de test.

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

Sélectionnez votre runsettings fichier. Pas votre fichier testsettings.


Vous devriez maintenant pouvoir exécuter vos tests sans problème.

 image showing that the tests are okay

Limites MSTest

  • Notez que MSTest fonctionnera uniquement avec les projets de test d'unité compilés en tant que CPU. Un projet de test x64 ne montrera aucun test sous Test Explorer.

  • L'assemblage à tester peut être x64, mais la bibliothèque de tests unitaires elle-même doit être Toute CPU. 

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

1
jrh

Après avoir suivi cet article de blog , ce qui suit, exécuté à partir d'une invite de commande VS (CorFlags.exe se trouve dans PATH), exécute les tests de ma solution jouet:

@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

Il reste à voir comment cela se comportera par rapport au code de production réel.

1
David

En plus de la solution @Anupam, sur VS2013, vous pouvez accéder à TEST> Paramètres de test> Architecture de processeur par défaut et choisir entre X86 et X64 . C'est presque la même chose que de sélectionner un fichier de paramètres de test, sauf que vous n'avez pas besoin de ce fichier pour spécifier uniquement la plate-forme de test.

0
fernacolo

Merci pour le conseil sur Resharper, car il indique que le problème pourrait être évité en passant à MSTest. Je ne pouvais pas faire travailler Resharper. Tester un fichier tiers tiers 64 bits DLL même si vous vous contentez de vous moquer de lui (il reste à le charger) ne semble fonctionner qu'avec MsTest en mode 64 bits. L'option Resharper de MSTest pour "Utiliser cette configuration de test" comporte uniquement l'option "Par défaut" en tant qu'option déroulante et "Modifier" est estompé. L’autre paramètre "Utiliser la configuration d’exécution de test spécifiée dans le fichier de métadonnées" ne fonctionne pas non plus et cela suppose que l’on sache quoi ou à quel emplacement se trouve ce fichier de métadonnées. Resharper ne fonctionnerait pas en mode 64 bits comme le prouve la variable d'environnement Is64BitProcess ci-dessus. (VS 2013 Update 4, Resharper 8.2)

0
Wray Smallwood