“Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information”
Voici le petit message d’amour que peut vous renvoyez votre ami la CLR lorsque vous essayez d’exécuter une application qui :
- référence une assembly mixte (mêlant code natif et code managé) qui a été compilée pour être basée sur une version différente de la CLR utilisée par votre point d’entrée.
La solution à ce problème est assez simple, il suffit de rajouter une section dans votre fichier de config :
<configuration> <startup useLegacyV2RuntimeActivationPolicy=
"true"> <supportedRuntime version=
"v4.0"/> </startup> </configuration> L’attribut useLegacyV2RuntimeActivationPolicy
La clé du problème se situe donc dans l’utilisation de l’attribut useLegacyV2RuntimeActivationPolicy qui est à false par défaut. Cet attribut permet de changer la politique de chargement de CLR au sein de votre application. Il y a eu en effet un gros changement à ce sujet :
-
Dans l’ère pré-CLR V4, en V2 quoi, il n’était possible de charger qu’une seule version de CLR au sein d’un process. La politique par défaut était de charger toutes vos assemblies en utilisant la version la plus récente de la CLR que vous aviez à disposition. Cette stratégie a comme avantage que votre ancien code bénéficie automatiquement des améliorations apportées par des versions plus récentes de CLR. Mais cela pouvait posait des problèmes de compatibilité dans certains rares cas.
-
Avec la CLR V4, il est à présent de charger différentes versions de CLR au sein d’un même process et afin de ne plus être confronté aux problèmes de compatibilité la politique de chargement a changé. A présent les assemblies basées sur la CLR 4, utilisent la CLR 4, et les autres utilisent la version la plus récente inférieure à la V4.
Le problème avec les assemblies mixtes c’est que la CLR doit être capable de savoir quelle est la CLR a utiliser lorsque un thread natif appel du code managé. Il faut donc désactiver le side by side afin d’avoir une seule version identifiable.
Mais pourquoi ça marche très bien depuis mes tests unitaires ?
Confronté au problème une de mes premières questions a été de comprendre pourquoi mon code fonctionne très bien depuis mes tests unitaires alors qu’il plante lorsque je l’appelle depuis mon application. Le moteur d’exécution des tests unitaires MSTest est QTAgent.exe (QTAgent32.exe en version 32 bits, et oui VS 2010 supporte enfin l’exécution de tests unitaires en 32 et 64 bits). Si l’on va farfouiller un petit peu dans le dossier C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE à la recherche des fichiers de configs des tests runners on se rend compte que Microsoft a configuré le chargement de runtime via le fameux attribut useLegacyV2RuntimeActivationPolicy.
Ce qui veut donc dire que par défaut tous vos tests unitaires utiliseront uniquement la V4 de la CLR et que le hosting de CLR Side by Side est désactivé pour tous vos tests unitaires.