Comment puis-je corriger l'erreur de compilation de Visual Studio, «incompatibilité entre l'architecture de processeur»?

459

Je suis nouveau dans la configuration de projet dans Visual Studio 2010, mais j'ai fait des recherches et je n'arrive toujours pas à comprendre ce problème. J'ai une solution Visual Studio avec une DLL C ++ référençant la DLL C #. La DLL C # fait référence à quelques autres DLL, certaines au sein de mon projet et d'autres externes. Lorsque j'essaie de compiler la DLL C ++, j'obtiens cet avertissement:

avertissement MSB3270: il y avait un décalage entre l'architecture de processeur du projet en cours de génération "MSIL" et l'architecture de processeur de la référence "[DLL C # interne]", "x86".

Il me dit d'aller dans Configuration Manager pour aligner mes architectures. La DLL C # est configurée avec la plate-forme cible x86. Si j'essaye de changer cela en quelque chose d'autre, comme Any CPU, il se plaint car l'une des DLL externes dont il dépend a la cible de plate-forme x86.

Lorsque je regarde Configuration Manager, il montre la plate-forme pour ma DLL C # en tant que x86 et pour mon projet C ++ en tant que Win32. Cela semble être la bonne configuration; Je ne veux sûrement pas que le projet de mon projet C ++ ait une plate-forme définie sur x64, qui est la seule autre option présentée.

Qu'est-ce que je fais mal ici?

Paul Eastlund
la source
Quelle est la plainte, en particulier, lorsque vous la remplacez par Any CPU?
lordcheeto
2
Je n'ai pas assez d'informations pour faire une suggestion éclairée, mais faites un clic droit sur votre solution -> Ordre de construction du projet et assurez-vous que votre projet C # est en cours de construction avant le projet C ++. Si ce n'est pas le cas, accédez à l'onglet Dépendances et indiquez à VS que le projet C ++ dépend du projet C #.
lordcheeto du
2
Visual Studio est encore une fois merde à ce sujet. La plate-forme en haut de mon écran indique x64 mais l'avertissement indique que le projet en cours de construction est "MSIL". Visual Studio me dit donc qu'il y a un décalage entre les pommes et les oranges lorsque je n'utilise pas de pommes. Pouvons-nous le renommer Visual Stupido?
Paul McCarthy
Pour moi, c'est un bogue dans Visual Studio. Je sélectionne x64 comme cible de plate-forme et cela me dit que le projet est en cours de construction pour MSIL.
Paul McCarthy
La réponse courte est que si votre projet a des dépendances sur x86 ou x64, vous ne pouvez pas utiliser Any CPU (qui est uniquement pour les applications .NET pures). Vous devez donc construire pour x64 ou x32, pas pour n'importe quel CPU. Ceci est dérivé de la réponse
zar

Réponses:

513

Cet avertissement semble avoir été introduit avec la nouvelle version bêta de Visual Studio 11 et .NET 4.5, bien que je suppose que cela aurait pu être possible auparavant.

Tout d'abord, ce n'est qu'un avertissement. Cela ne devrait rien faire de mal si vous traitez simplement des dépendances x86. Microsoft essaie simplement de vous avertir lorsque vous déclarez que votre projet est compatible avec «Any CPU» mais que vous avez une dépendance sur un projet ou un assembly .dll qui est x86 ou x64. Parce que vous avez une dépendance x86, techniquement votre projet n'est donc pas compatible "Any CPU". Pour faire disparaître l'avertissement, vous devez réellement changer votre projet de "Any CPU" en "x86". C'est très simple à faire, voici les étapes.

  1. Accédez à l'élément de menu Build | Configuration Manager.
  2. Trouvez votre projet dans la liste, sous Plate-forme il dira "N'importe quel CPU"
  3. Sélectionnez l'option "Any CPU" dans le menu déroulant, puis sélectionnez <New..>
  4. Dans cette boîte de dialogue, sélectionnez x86 dans la liste déroulante "Nouvelle plate-forme" et assurez-vous que "Tout processeur" est sélectionné dans la liste déroulante "Copier les paramètres de".
  5. Appuyez sur OK
  6. Vous souhaiterez sélectionner x86 pour les configurations de débogage et de version.

Cela fera disparaître l'avertissement et indiquera également que votre assemblage ou projet n'est plus compatible avec "N'importe quel CPU" mais est désormais spécifique à x86. Ceci est également applicable si vous générez un projet 64 bits qui a une dépendance x64; vous devez simplement sélectionner x64 à la place.

Une autre remarque, les projets peuvent être compatibles avec "N'importe quel CPU" généralement s'ils sont de purs projets .NET. Ce problème ne survient que si vous introduisez une dépendance (DLL tierce ou votre propre projet géré C ++) qui cible une architecture de processeur spécifique.

David Sacks
la source
3
Je viens d'installer le RTW de Visual Studio 2012 et j'ai ouvert une solution 2010 préexistante et j'ai commencé à voir le même avertissement, c'est donc quelque chose qui existe toujours dans le RTW.
Tod Thomson
4
Cela étant dit, je pense que la réponse de David est correcte, cet avertissement vous fait savoir que votre application n'est vraiment pas "AnyCPU", vous rencontrerez donc des problèmes lorsque vous la déploierez finalement sur la mauvaise architecture.
Tod Thomson
6
Cela PEUT très bien blesser quelque chose. Un exe Any CPU se chargera en tant que x64 sur un système d'exploitation 64 bits et ne pourra pas charger les DLL x86. Donc, si vous avez une dépendance sur une plate-forme particulière, vous devez vraiment configurer votre plate-forme correctement.
Yaur
1
Le menu Build semble manquer dans VS C # 2010 Express. Comment y accéder? J'aimerais qu'ils ne cachent rien.
Xonatron
1
Je viens de découvrir comment activer le menu de construction dans Visual Studio 2010 Express: menu Outils -> Paramètres -> sélectionnez «Paramètres experts»
Xonatron
144

Il s'agit d'un avertissement très têtu et bien qu'il s'agisse d'un avertissement valide, il existe certains cas où il ne peut pas être résolu en raison de l'utilisation de composants tiers et pour d'autres raisons. J'ai un problème similaire, sauf que l'avertissement est dû au fait que ma plateforme de projets est AnyCPU et que je fais référence à une bibliothèque MS conçue pour AMD64. Cela se trouve dans Visual Studio 2010 et semble avoir été introduit en installant VS2012 et .Net 4.5.

Étant donné que je ne peux pas modifier la bibliothèque MS à laquelle je fais référence et que je sais que mon environnement de déploiement cible ne sera que 64 bits, je peux ignorer ce problème en toute sécurité.

Et l'avertissement? Microsoft a publié en réponse à un rapport Connect qu'une option consiste à désactiver cet avertissement. Vous ne devez le faire que si vous êtes très conscient de l'architecture de votre solution et que vous comprenez parfaitement votre cible de déploiement et que vous savez que ce n'est pas vraiment un problème en dehors de l'environnement de développement.

Vous pouvez modifier votre fichier de projet et ajouter ce groupe de propriétés et ce paramètre pour désactiver l'avertissement:

<PropertyGroup>
  <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
Gio Palacino
la source
1
La seule autre référence MS officielle à cette solution que j'ai vue se trouve dans le fichier Lisezmoi RC ​​de Microsoft .NET Framework 4.5 . Étrangement, il a été supprimé du fichier Lisezmoi RTM.
JohnC
4
Cela fonctionne, mais pas pour une variante de l'avertissement: "L'assembly référencé ... cible un processeur différent de l'application". Ce serait formidable s'il y avait un paramètre similaire pour cet avertissement?
Jimmy
6
"ma plateforme de projets est AnyCPU et je fais référence à une bibliothèque MS conçue pour AMD64" ... C'est FAUX. Étant donné que votre déploiement cible est toujours 64 bits, vous pouvez définir votre plate-forme sur x64, ce qui crée une erreur plus appropriée si votre hypothèse 64 bits est violée et empêche également l'avertissement.
Ben Voigt
2
@BenVoigt est une excellente idée en théorie, mais VS étant un processus x86 a besoin de versions x86 de contrôles pour exécuter des choses comme le Concepteur de formulaires Windows, même si votre application ne sera que 64 bits. C'est une raison valable, mais malheureuse, d'utiliser une fausse build "Any CPU".
jrh
1
@jrh: Ensuite, placez l'interface graphique dans un projet DLL et générez -le en tant que AnyCPU. L'EXE doit être marqué avec la bonne architecture pour correspondre aux dépendances natives. Une bonne séparation de l'interface graphique de la logique va très loin (bien qu'elle ait toujours ses limites, comme lorsque le code natif rend une partie de l'interface graphique, mais la prise en charge du concepteur est une cause perdue à moins que vous ne construisiez l'intégralité du projet pour les deux). x86 et x64)
Ben Voigt
61

Une bonne règle de base est «DLL ouvertes, EXE fermés», c'est-à-dire:

  • EXE cible le système d'exploitation, en spécifiant x86 ou x64.
  • Les DLL sont laissées ouvertes (c'est-à-dire AnyCPU) afin qu'elles puissent être instanciées dans un processus 32 bits ou 64 bits.

Lorsque vous créez un EXE en tant que AnyCPU, tout ce que vous faites est de reporter la décision sur le processus à utiliser pour le système d'exploitation, qui JIT l'EXE à son goût. Autrement dit, un système d'exploitation x64 créera un processus 64 bits, un système d'exploitation x86 créera un processus 32 bits.

La création de DLL en tant que AnyCPU les rend compatibles avec les deux processus.

Pour plus d'informations sur les subtilités du chargement des assemblages, voir ici . Le résumé exécutif se lit comme suit:

  • AnyCPU - se charge en tant qu'assemblage x64 ou x86, selon le processus d'appel
  • x86 - charge en tant qu'assemblage x86; ne se chargera pas à partir d'un processus x64
  • x64 - charge en assemblage x64; ne se chargera pas à partir d'un processus x86
Gustavo Mori
la source
4
Cette règle est logique pour moi. Mais considérez la situation suivante: Native.dll (x64) utilisé par NetA.dll (Any CPU) utilisé par NetB.dll (Any CPU) utilisé par App1.exe (x64). Il n'y a pas de vrai problème ici, mais la compilation de NetA.dll me donne l'avertissement. OK, puisque cet assemblage dépend directement de Native.dll, je pourrais également le marquer comme x64. Mais alors la compilation de NetB.dll se plaint. Je souhaite conserver NetB.dll en tant que "Tout processeur" car il s'agit d'un assembly commun utilisé dans une application différente, pure dot-net. Je conclus que ma seule option est de supprimer / ignorer l'avertissement. Oui?
Steve Robbins
2
En raison de la dépendance à Native.dll, votre lignage d'application / assemblage entier est maintenant x64, que vous supprimiez l'avertissement ou non. Bien que la suppression fonctionne dans votre scénario, des situations étranges pourraient survenir à l'avenir. Par exemple, 1) l'assembly NetB est utilisé dans un environnement x86, où Nativex64 ne se charge pas, ou 2) votre client souhaite une version x86 d'App1.exe, et vous compilez avec bonheur, car NetB est marqué comme n'importe quel CPU, mais encore une fois, Nativex64 en haut de la pile ne se chargera pas
Gustavo Mori
Bien que la règle de Gustavo soit un bon principe, elle ne peut pas être utilisée pour le problème spécifique posé dans cette question car le projet dépend déjà d'un assemblage tiers qui n'a pas respecté la règle (c'est x86, pas AnyCPU). Par conséquent, tant que la dépendance existe, toute la chaîne de projets doit cibler x86 et rien d'autre.
David Burg
23

La DLL C # est configurée avec la plate-forme cible x86

Quel est le type de problème, une DLL ne choisit pas réellement le bitness du processus. Cela est entièrement déterminé par le projet EXE, c'est le premier assemblage qui est chargé, donc son paramètre cible de plate-forme est celui qui compte et définit le témoin du processus.

Les DLL n'ont pas le choix, elles doivent être compatibles avec le processus bitness. S'ils ne le sont pas, vous obtiendrez un gros Kaboom avec une BadImageFormatException lorsque votre code essaie de les utiliser.

Donc, une bonne sélection pour les DLL est AnyCPU afin qu'elles fonctionnent dans les deux sens. Qui fait beaucoup de sens pour les DLL C #, ils font le travail de toute façon. Mais bien sûr, pas votre DLL en mode mixte C ++ / CLI, elle contient du code non managé qui ne peut bien fonctionner que lorsque le processus s'exécute en mode 32 bits. Vous pouvez obtenir le système de génération pour générer des avertissements à ce sujet. C'est exactement ce que tu as. Juste des avertissements, il se construit toujours correctement.

Punt juste le problème. Définissez la cible de plate-forme du projet EXE sur x86, cela ne fonctionnera avec aucun autre paramètre. Et conservez tous les projets DLL sur AnyCPU.

Hans Passant
la source
1
Donc, pour être clair: je ne construis pas l'EXE, je construis une DLL à exécuter avec l'EXE de quelqu'un d'autre. La modification de la cible de plate-forme des DLL C # sur N'importe quel processeur n'élimine pas l'avertissement. Je me demande si c'est un cas de connect.microsoft.com/VisualStudio/feedback/details/728901/… - J'ignorerais l'avertissement lui-même mais en fait, l'EXE est capable de charger la DLL C # mais pas la DLL C ++ donc je pense que c'est un vrai problème.
Paul Eastlund
Utilisez-vous en fait VS2010? Il n'était pas clair non plus du tout que vous ne pouviez pas charger la DLL C ++ / CLI. Quel est le diagnostic? Mettez à jour vos questions avec ces informations essentielles.
Hans Passant
Je n'avais pas posté sur l'échec de la charge car je n'étais pas sûr à 100% qu'il était connecté, et lors d'un débogage ultérieur, il s'avère que ce n'est pas le cas. J'utilise VS2010. Texte de question mis à jour. Très désolé pour la confusion
Paul Eastlund
1
Vous n'avez documenté aucune sorte d'erreur ou d'exception liée au chargement de la DLL. Je ne peux pas vous aider si vous ne me dites pas ce que vous savez. Bonne chance.
Hans Passant
5

J'obtenais le même avertissement que j'ai fait ceci:

  1. décharger le projet
  2. modifier les propriétés du projet, par exemple .csproj
  3. ajoutez la balise suivante:

    <PropertyGroup>
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
            None
        </ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
  4. Recharger le projet

yogeshwar gutte
la source
2
Cela ne résout pas le problème. C'est juste désactiver l'avertissement pour le projet particulier. Mais dans certains cas, je trouve que c'est une solution valable. Merci!
Tiny
4

J'ai eu ce problème aujourd'hui et simplement regarder les configurations de construction dans Visual Studio n'aidait pas car il montrait N'importe quel CPU à la fois pour le projet qui n'était pas en cours de construction et le projet référencé.

J'ai ensuite regardé dans le csproj du projet référencé et trouvé ceci:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>

D'une manière ou d'une autre, ce PlatformTarget a été ajouté au milieu d'un changement de configuration et l'IDE ne semblait pas le voir.

La suppression de cette ligne du projet référencé a résolu mon problème.

JBourne
la source
Il m'a fallu une journée entière pour comprendre cela. Merci beaucoup! :)
SohamC
3

Si votre DLL C # a des dépendances basées sur x86, alors votre DLL elle-même devra être x86. Je ne vois pas vraiment de solution. VS se plaint de le changer en (par exemple) x64 car un exécutable 64 bits ne peut pas charger des bibliothèques 32 bits.

Je suis un peu confus quant à la configuration du projet C ++. Le message d'avertissement fourni pour la version suggère qu'elle était ciblée pour AnyCPU, car elle a signalé que la plate-forme qu'elle ciblait était [MSIL], mais vous avez indiqué que la configuration du projet était en fait Win32. Une application Win32 native ne devrait pas impliquer le MSIL - bien qu'il soit probable que la prise en charge CLR soit activée si elle interagit avec une bibliothèque C #. Je pense donc qu'il y a quelques lacunes du côté de l'information.

Puis-je vous demander respectueusement de revoir et de publier un peu plus en détail la configuration exacte des projets et la façon dont ils sont interdépendants? Soyez heureux de vous aider si possible.

David W
la source
3

En plus de répondre David Sacks, vous devrez peut - être aller à l' Buildonglet du Project Propertieset ensemble Platform Targetà x86pour le projet qui vous donne ces avertissements. Bien que vous puissiez vous y attendre, ce paramètre ne semble pas être parfaitement synchronisé avec celui du gestionnaire de configuration.

Dave Cousineau
la source
2

Pour les projets C #, la cible de x86 fait ce que cela ressemble. Il indique que cet assemblage ne prend en charge que les architectures x86. De même pour x64. D'un autre côté, tout processeur dit que je ne me soucie pas de l'architecture, je prends en charge les deux. Ainsi, les 2 questions suivantes sont (1) quelle est la configuration de l'exécutable qui utilise ces DLL? et (2) quel est le témoinde votre OS / ordinateur? La raison pour laquelle je pose la question est que si votre exécutable est compilé pour s'exécuter en 64 bits, alors il A BESOIN de toutes les dépendances pour pouvoir également s'exécuter en mode 64 bits. Votre assemblage Any CPU devrait pouvoir être chargé, mais il fait peut-être référence à une autre dépendance qui n'est capable de s'exécuter qu'en configuration x86. Vérifiez toutes les dépendances et dépendances-de-dépendances pour vous assurer que tout est "Any CPU" ou "x64" si vous prévoyez d'exécuter l'exécutable en mode 64 bits. Sinon, vous aurez des problèmes.

À bien des égards, Visual Studio ne facilite pas la compilation d'un mélange de CPU et de divers assemblys dépendants de l'architecture. C'est faisable, mais cela nécessite souvent qu'un assemblage qui serait autrement "N'importe quel CPU" doive être compilé séparément pour x86 et x64 car certaines dépendances d'une dépendance ont quelque part deux versions.

Jonathan DeCarlo
la source
La configuration de l'exécutable est-elle pertinente puisque j'obtiens un échec juste en essayant de construire les DLL? (C'est x86 cependant.) Mon ordinateur est x64.
Paul Eastlund
2
C'est l'exécutable qui détermine quel témoin sera utilisé. Si l'exécutable s'exécute en tant que x64, alors tout ce qu'il charge (directement ou indirectement) doit être x64 ou Any CPU. Si l'exécutable s'exécute en tant que x86, tout ce qui est chargé (directement ou indirectement) doit être x86 ou Any CPU.
Jonathan DeCarlo
1

J'ai déjà rencontré un problème similaire, en particulier lors de l'ajout d'une solution de test à une solution x64 existante, comme SharePoint. Dans mon cas, cela semble avoir à voir avec le fait que certains modèles de projet sont ajoutés comme certaines plates-formes par défaut.

Voici la solution qui fonctionne souvent pour moi: définissez tout sur la bonne plateforme dans Configuration Manager (la liste déroulante de configuration active, dit Debug normalement, est un bon moyen d'y accéder) et la plateforme de projet (dans les propriétés du projet), puis construire, puis tout remettre à AnyCPU. Parfois, je dois supprimer et rajouter certaines dépendances (DLL dans les propriétés de chaque projet) et parfois "Exécuter les tests dans un processus 32 bits ou 64 bits" (double-cliquer sur Local.testsettings et aller sur Hosts) doit être modifié.

Il me semble que cela ne fait que fixer quelque chose puis le remettre en place, mais il se passe probablement plus de choses dans les coulisses que je ne vois pas. Cela a fonctionné assez régulièrement pour moi dans le passé.

ssamuel
la source
1

Pour mon projet, j'ai besoin de pouvoir construire à la fois sur x86 et x64. Le problème avec cela est que chaque fois que vous ajoutez des références lors de l'utilisation de l'une, cela se plaint lorsque vous créez l'autre.

Ma solution consiste à éditer manuellement les fichiers * .csproj afin que des lignes comme celles-ci:

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86"/>

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64"/>

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"/>

changer pour ceci:

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral"/>
Thick_propheT
la source
1

J'ai eu un problème similaire dû à la DLL de test MS UNIT. Mon application WPF a été compilée en tant que x86 mais la DLL de test unitaire (fichier EXE référencé) en tant que "Any CPU". J'ai changé la DLL de test unitaire pour être compilée pour x86 (identique à EXE) et elle a été résolue.

user1257110
la source
0

Il devrait y avoir un moyen de créer un .NET EXE / DLL AnyCPU, et toutes les DLL non gérées dont il dépend compilées à la fois avec x86 et x64, les deux regroupées peut-être avec des noms de fichiers différents, puis le module .NET chargeant dynamiquement le bon en fonction de son exécution architecture du processeur. Cela rendrait AnyCPU puissant. Si la DLL C ++ ne prend en charge que x86 ou x64, AnyCPU est bien sûr inutile. Mais l'idée de regroupement des deux que je n'ai pas encore vue implémentée car le gestionnaire de configuration ne fournit même pas un moyen de construire deux fois le même projet avec une configuration / plate-forme différente pour un regroupement multiple permettant à AnyCPU ou même à d'autres concepts comme n'importe quelle configuration d'être possible.

Gregory Morse
la source
2
bienvenue sur stackoverflow! pouvez-vous essayer de concentrer / reformater un peu cette réponse?
Corley Brigman
On dirait que cela ferait une bonne question, ou un article de blog ou une demande de fonctionnalité sur Connect ... cela ne répond pas réellement à celle-ci.
Ben Voigt
0

J'ai eu un avertissement très similaire dans ma version. Mes projets ont été définis pour cibler .NET 4.5, sur le serveur de build, le SDK Windows 8.1 (pour .NET 4.5.1) a été installé. Après avoir mis à jour mes projets pour cibler .NET 4.5.1 (ce n'était pas un problème pour moi, c'était pour une application complètement nouvelle), je n'ai plus reçu d'avertissement ...

NicoCV
la source
0

J'ai résolu cet avertissement en changeant "Configuration Manager" en Release (Mixed Plataform).

Edu Pelais
la source
0

J'ai reçu cet avertissement dans Visual Studio 2012 lors de la compilation d'une tâche de script de pipeline SSIS SQL Server 2012 SP1 - jusqu'à ce que j'installe SQL Server 2012 SP2.

cdonner
la source
0

J'ai eu le même problème avec l'ouverture de la connexion SQLite, et l'utilisation du Nuget et l'installation du composant utilisé dans le projet (SQLite) l'ont corrigé! essayez d'installer votre composant de cette façon et vérifiez le résultat

StudioX
la source