Как исправить ошибку компиляции Visual Studio, «несоответствие между процессорной архитектурой»?

459

Я новичок в настройке проекта в Visual Studio 2010, но я провел некоторые исследования и до сих пор не могу понять эту проблему. У меня есть решение Visual Studio с C ++ DLL, ссылающейся на C # DLL. C # DLL ссылается на несколько других DLL, некоторые в моем проекте, а некоторые внешние. Когда я пытаюсь скомпилировать C ++ DLL, я получаю это предупреждение:

предупреждение MSB3270: Произошло несоответствие между архитектурой процессора проекта, в котором выполняется сборка "MSIL", и архитектурой процессора из ссылок "[internal C # dll]", "x86".

Он говорит мне пойти в Configuration Manager, чтобы выровнять мои архитектуры. DLL C # настроена с целевой платформой x86. Если я пытаюсь изменить это на что-то другое, например, на Любой ЦП, он жалуется, потому что у одной из внешних DLL-библиотек, от которой он зависит, есть целевая платформа x86.

Когда я смотрю на Configuration Manager, он показывает Платформу для моей C # DLL как x86 и для моего C ++ проекта как Win32. Это похоже на правильную настройку; Конечно, я не хочу, чтобы в моем проекте на C ++ была установлена ​​платформа x64, что является единственным предложенным вариантом.

Что я здесь не так делаю?

Пол Истлунд
источник
В чем претензия, в частности, когда вы меняете его на Any CPU?
Lordcheeto
2
У меня недостаточно информации, чтобы сделать обоснованное предложение, но щелкните правой кнопкой мыши на вашем решении -> Порядок сборки проекта и убедитесь, что ваш проект C # создается перед проектом C ++. Если это не так, перейдите на вкладку Зависимости и сообщите VS, что проект C ++ зависит от проекта C #.
Lordcheeto
2
Visual Studio снова дерьмо на это. Платформа в верхней части экрана показывает x64, но в предупреждении говорится, что строящийся проект - «MSIL». Так что Visual Studio говорит мне, что есть несоответствие между яблоками и апельсинами, когда я не использую яблоки. Можем ли мы переименовать его в Visual Stupido?
Пол Маккарти
Насколько я понимаю, это ошибка в Visual Studio. Я выбираю x64 в качестве целевой платформы, и он говорит мне, что проект собирается для MSIL.
Пол Маккарти
Короткий ответ: если ваш проект зависит от x86 или x64, вы не можете использовать любой процессор (который предназначен только для приложений .NET). Таким образом, вы должны собрать для x64 или x32, а не для любого процессора. Это вытекает из ответа
Зар

Ответы:

513

Это предупреждение, по-видимому, появилось в новых бета-версиях Visual Studio 11 и .NET 4.5, хотя я полагаю, что это могло быть возможно раньше.

Во-первых, это действительно просто предупреждение. Это не должно повредить ничего, если вы просто имеете дело с зависимостями x86. Microsoft просто пытается предупредить вас, когда вы заявляете, что ваш проект совместим с «любым процессором», но у вас есть зависимость от проекта или сборки .dll, которая является либо x86, либо x64. Поскольку у вас есть зависимость от x86, технически ваш проект не совместим с любым процессором. Чтобы предупреждение исчезло, вы должны изменить свой проект с «Любой процессор» на «x86». Это очень легко сделать, вот шаги.

  1. Перейдите в пункт меню Build | Configuration Manager.
  2. Найдите свой проект в списке, в разделе «Платформа» будет указано «Любой процессор».
  3. Выберите опцию «Любой процессор» из выпадающего списка, а затем выберите <New..>
  4. В этом диалоговом окне выберите x86 из выпадающего меню «Новая платформа» и убедитесь, что в выпадающем меню «Копировать настройки из» выбран «Любой процессор».
  5. Хит ОК
  6. Вы захотите выбрать x86 для конфигурации Debug и Release.

Это заставит предупреждение исчезнуть, а также заявит, что ваша сборка или проект больше не совместимы с «любым процессором», но теперь относятся только к x86. Это также применимо, если вы создаете 64-битный проект с зависимостью x64; вместо этого вы просто выбрали бы x64.

Еще одно замечание: проекты могут быть совместимы с любым процессором, как правило, если они являются чистыми проектами .NET Эта проблема возникает только в том случае, если вы вводите зависимость (сторонний dll или ваш собственный проект, управляемый C ++), который нацелен на конкретную архитектуру процессора.

Дэвид Сакс
источник
3
Я только что установил RTW Visual Studio 2012 и открыл существующее решение 2010 года и начал видеть то же самое предупреждение, так что это то, что все еще существует в RTW.
Тод Томсон
4
При этом, я думаю, что ответ Дэвида правильный, это предупреждение дает вам понять, что ваше приложение на самом деле не «AnyCPU», поэтому вы столкнетесь с проблемами, когда в конечном итоге развернете его на неправильной архитектуре.
Тод Томсон
6
Это очень хорошо может повредить что-то. Любой exe-процессор будет загружен как x64 на 64-битной ОС и не сможет загрузить dll x86. Поэтому, если у вас есть зависимость от конкретной платформы, вам действительно следует правильно настроить свою платформу.
Яур
1
Кажется, что меню Build отсутствует в VS C # 2010 Express. Как мне добраться до этого? Я хотел бы, чтобы они не скрывали вещи.
Ксонатрон
1
Только что узнал, как включить меню сборки в Visual Studio 2010 Express: меню Сервис -> Настройки -> выбрать «Настройки эксперта»
Xonatron
144

Это очень упрямое предупреждение, и, хотя оно является действительным предупреждением, в некоторых случаях его невозможно устранить из-за использования сторонних компонентов и по другим причинам. У меня похожая проблема, за исключением того, что предупреждение вызвано тем, что моей платформой проектов является AnyCPU, и я ссылаюсь на библиотеку MS, созданную для AMD64. Это в Visual Studio 2010, кстати, и, кажется, вводится путем установки VS2012 и .Net 4.5.

Поскольку я не могу изменить библиотеку MS, на которую я ссылаюсь, и поскольку я знаю, что моя целевая среда развертывания будет только 64-битной, я могу смело игнорировать эту проблему.

Как насчет предупреждения? Microsoft опубликовала в ответ на отчет Connect, что одним из вариантов является отключение этого предупреждения. Это следует делать только в том случае, если вы хорошо знакомы с архитектурой своего решения и полностью понимаете цель развертывания и знаете, что на самом деле это не проблема вне среды разработки.

Вы можете отредактировать файл проекта и добавить эту группу свойств и настройки, чтобы отключить предупреждение:

<PropertyGroup>
  <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
Джо Паласино
источник
1
Единственное официальное упоминание MS об этом решении, которое я видел, находится в файле Readme для Microsoft .NET Framework 4.5 RC . Странно это было удалено из файла RTM Readme.
JohnC
4
Это работает, но не для варианта предупреждения: «Ссылочная сборка ... предназначена для другого процессора, чем приложение». Было бы здорово, если бы для этого предупреждения была похожая настройка?
Джимми
6
«Платформа моих проектов - AnyCPU, и я ссылаюсь на библиотеку MS, созданную для AMD64» ... Это НЕПРАВИЛЬНО. Поскольку целевое развертывание всегда 64-битное, вы можете установить платформу на x64, что делает более подходящей ошибку, если ваше 64-битное предположение когда-либо нарушается, а также предотвращает предупреждение.
Бен Фойгт
2
@BenVoigt отличная идея в теории, но для того, чтобы VS был процессом x86, нужны сборки x86 для управления такими вещами, как конструктор Windows Forms, даже если ваше приложение будет только 64-битным. Это допустимая, но неудачная причина использовать ложную сборку «Любой процессор».
JRH
1
@jrh: Затем поместите GUI в проект DLL и сборки , что , как AnyCPU. EXE должен быть отмечен с правильной архитектурой, чтобы соответствовать родным зависимостям. Правильное отделение GUI от логики проходит долгий путь (хотя у него все еще есть свои ограничения, например, когда нативный код рендерит часть GUI, но поддержка конструктора будет проиграна, если вы не создадите сборки всего проекта для обоих x86 и x64)
Бен Фойгт
61

Хорошее практическое правило - «открытые DLL, закрытые EXE», то есть:

  • EXE предназначен для ОС, указав x86 или x64.
  • Библиотеки DLL остаются открытыми (т. Е. AnyCPU), поэтому их можно создавать в 32-битном или 64-битном процессе.

Когда вы создаете EXE-файл как AnyCPU, все, что вы делаете, - это откладываете решение о том, какой битрейт процесса использовать в ОС, что позволит JIT EXE-файла по своему вкусу. То есть ОС x64 создаст 64-битный процесс, ОС x86 создаст 32-битный процесс.

Создание DLL как AnyCPU делает их совместимыми с любым процессом.

Подробнее о тонкостях сборки сборки смотрите здесь . Резюме гласит что-то вроде:

  • AnyCPU - загружается как сборка x64 или x86, в зависимости от процесса вызова
  • x86 - загружается как сборка x86; не будет загружаться из процесса x64
  • x64 - загружается как сборка x64; не будет загружаться из процесса x86
Густаво Мори
источник
4
Это правило имеет смысл для меня. Но рассмотрим следующую ситуацию: Native.dll (x64), используемый NetA.dll (любой ЦП), используемый NetB.dll (любой ЦП), используемый App1.exe (x64). Здесь нет реальной проблемы, но компиляция NetA.dll дает мне предупреждение. Хорошо, так как эта сборка напрямую зависит от Native.dll, я мог бы также пометить ее как x64. Но потом компиляция NetB.dll жалуется. Я хочу сохранить NetB.dll как «Любой ЦП», потому что это обычная сборка, используемая в другом приложении с чисто точечными сетями. Я делаю вывод, что мой единственный вариант - подавить / проигнорировать предупреждение. Да?
Стив Роббинс
2
Из-за зависимости от Native.dll вся линия вашего приложения / сборки теперь x64, независимо от того, подавляете вы предупреждение или нет. Хотя подавление работает в вашем сценарии, в будущем могут возникнуть странные ситуации. Например, 1) сборка NetB используется в среде x86, где Nativex64 не будет загружаться, или 2) ваш клиент хочет версию App1.exe для x86, и вы скомпилируетесь удачно, поскольку NetB помечен как любой ЦП, но опять же, Nativex64 на вершине стека не будет загружаться
Густаво Мори
Хотя правило Густаво является хорошим принципом, его нельзя использовать для решения конкретной проблемы, поставленной в этом вопросе, поскольку проект уже имеет зависимость от сторонней сборки, которая не следует этому правилу (это x86, а не AnyCPU). Следовательно, пока существует зависимость, вся цепочка проектов должна быть нацелена на x86 и ничего больше.
Дэвид Бург
23

C # DLL настроена с платформой target x86

В этом и заключается проблема, DLL фактически не может выбрать, какой будет степень процесса. Это полностью определяется проектом EXE, это первая сборка, которая загружается, поэтому ее целевым параметром Platform является тот, который считает и устанавливает битность для процесса.

У DLL нет выбора, они должны быть совместимы с разрядностью процесса. Если это не так, вы получите большой Kaboom с BadImageFormatException, когда ваш код попытается их использовать.

Поэтому хорошим выбором для DLL является AnyCPU, чтобы они работали в любом случае. То , что делает много смысла для библиотек DLL C #, они делают работу так или иначе. Но, конечно же, не ваша DLL C ++ / CLI в смешанном режиме, она содержит неуправляемый код, который может работать хорошо только тогда, когда процесс работает в 32-битном режиме. Вы можете заставить систему сборки генерировать предупреждения об этом. Что именно то, что вы получили. Только предупреждения, это все еще строит должным образом.

Просто разберись с проблемой. Установите для платформы проекта EXE целевую платформу x86, она не будет работать с другими настройками. И просто держите все проекты DLL в AnyCPU.

Ганс Пассант
источник
1
Итак, чтобы быть ясным: я не создаю EXE, я создаю DLL для запуска с чужим EXE. Изменение цели платформы библиотек C # на Any CPU не устраняет предупреждение. Мне интересно, если это случай connect.microsoft.com/VisualStudio/feedback/details/728901/… - я бы проигнорировал само предупреждение, но на самом деле EXE может загрузить DLL C #, но не C ++ DLL так что я думаю, что это настоящая проблема.
Пол Истлунд
Вы на самом деле используете VS2010? Также совершенно неясно, что вы не можете загрузить C ++ / CLI DLL. Что такое диагностика? Обновите ваши вопросы с этой важной информацией.
Ганс Пассант
Я не писал о сбое загрузки, потому что я не был на 100% уверен, что он был подключен, а при дальнейшей отладке оказывается, что нет. Я использую VS2010. Обновленный текст вопроса. Очень жаль за путаницу
Пол Истлунд,
1
Вы не документировали какие-либо ошибки или исключения, связанные с загрузкой DLL. Я не могу помочь вам, если вы не скажете мне, что вы знаете. Удачи с этим.
Ганс Пассант
5

Я получил то же самое предупреждение, я сделал это:

  1. выгрузить проект
  2. редактировать свойства проекта, т.е. .csproj
  3. добавьте следующий тег:

    <PropertyGroup>
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
            None
        </ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
  4. Перезагрузить проект

Йогешвар Гутт
источник
2
Это не решение проблемы. Это просто отключение предупреждения для конкретного проекта. Но в некоторых случаях я считаю это правильным решением. Спасибо!
Tiny
4

У меня была эта проблема сегодня, и просто просмотр конфигураций здания в Visual Studio не помог, потому что он показал Любой ЦП как для проекта, который не создавался, так и для ссылочного проекта.

Затем я посмотрел в csproj ссылочного проекта и нашел это:

<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>

Каким-то образом эта PlatformTarget была добавлена ​​в середине изменения конфигурации, и IDE, похоже, этого не видела.

Удаление этой строки из ссылочного проекта решило мою проблему.

JBourne
источник
Мне потребовался целый день, чтобы понять это. Большое спасибо! :)
SohamC
3

Если ваша C # DLL имеет зависимости на основе x86, то ваша DLL должна быть x86. Я действительно не вижу способа обойти это. VS жалуется на его изменение (например) x64, потому что 64-битный исполняемый файл не может загружать 32-битные библиотеки.

Я немного запутался в конфигурации проекта C ++. Предупреждающее сообщение, которое было предоставлено для сборки, говорит о том, что оно предназначено для AnyCPU, потому что в нем сообщалось, что целью платформы была [MSIL], но вы указали, что конфигурация для проекта на самом деле была Win32. Нативное приложение Win32 не должно включать MSIL - хотя, вероятно, ему нужно будет включить поддержку CLR, если оно взаимодействует с библиотекой C #. Так что я думаю, что есть несколько пробелов в информационной части.

Могу ли я с уважением попросить вас просмотреть и опубликовать более подробную информацию о точной конфигурации проектов и их взаимосвязи? Будем рады помочь, если это возможно.

Дэвид В.
источник
3

В дополнение к Дэвид Сакс ответ, вы можете также необходимо перейти на Buildвкладку Project Propertiesи набор Platform Targetдля x86для проекта , который дает вам эти предупреждения. Хотя вы, возможно, ожидаете, что этот параметр, похоже, не полностью синхронизирован с параметром в диспетчере конфигурации.

Дейв Кузино
источник
2

Для проектов C # цель x86 делает то, на что это похоже. Это говорит о том, что эта сборка поддерживает только архитектуры x86. Аналогично для x64. Любой процессор, с другой стороны, говорит, что мне все равно, какая архитектура, я поддерживаю обе. Итак, следующие 2 вопроса: (1) какова конфигурация исполняемого файла, который использует эти библиотеки? и (2) что такое битностьвашей ОС / компьютера? Причина, по которой я спрашиваю, заключается в том, что если ваш исполняемый файл скомпилирован для работы в 64-битной среде, тогда ему НУЖНЫ все зависимости, чтобы иметь возможность работать и в 64-битном режиме. Любая сборка ЦП должна быть в состоянии загружаться, но, возможно, она ссылается на некоторую другую зависимость, которая может работать только в конфигурации x86. Проверьте все зависимости и зависимости, чтобы убедиться, что все «Любой процессор» или «x64», если вы планируете запустить исполняемый файл в 64-битном режиме. В противном случае у вас будут проблемы.

Во многих отношениях Visual Studio не облегчает компиляцию смеси любых процессоров и сборок, зависящих от архитектуры. Это выполнимо, но часто требуется, чтобы сборка, которая в противном случае была бы «Любой ЦП», должна была быть скомпилирована отдельно для x86 и x64, потому что у некоторой зависимости зависимости есть где-то две версии.

Джонатан ДеКарло
источник
Уместна ли конфигурация исполняемого файла, поскольку я получаю ошибку только при попытке собрать библиотеки DLL? (Хотя x86.) Мой компьютер x64.
Пол Истлунд
2
Это исполняемый файл, который определяет, какая битность будет использоваться. Если исполняемый файл работает как x64, то все, что он загружает (прямо или косвенно), должно быть x64 или любым процессором. Если исполняемый файл работает как x86, то все, что загружается (прямо или косвенно), должно быть x86 или любым процессором.
Джонатан ДеКарло
1

У меня раньше была похожая проблема, особенно при добавлении тестового решения в существующее решение x64, такое как SharePoint. В моем случае, похоже, это связано с тем, что определенные шаблоны проектов добавляются в качестве определенных платформ по умолчанию.

Вот решение, которое часто работает для меня: установите все на правильную платформу в Configuration Manager (раскрывающийся список активной конфигурации, как обычно говорит Debug, это хороший способ добраться до него) и платформу проекта (в свойствах проекта), затем построить, затем установить все обратно на AnyCPU. Иногда мне приходится удалять и повторно добавлять некоторые зависимости (библиотеки DLL в свойствах каждого проекта), а иногда необходимо изменить «Выполнить тесты в 32-битном или 64-битном процессе» (дважды щелкните Local.testsettings и перейти к Hosts).

Мне кажется, что это просто установка чего-то, а затем его восстановление, но, вероятно, за кулисами происходит больше всего, чего я не вижу. Это работало довольно последовательно для меня в прошлом, хотя.

ssamuel
источник
1

Для моего проекта у меня есть требование иметь возможность сборки как на x86, так и на x64. Проблема заключается в том, что всякий раз, когда вы добавляете ссылки во время использования одной, она жалуется, когда вы создаете другую.

Мое решение состоит в том, чтобы вручную редактировать файлы * .csproj так, чтобы строки были такими:

<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"/>

переодеться в это:

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral"/>
Thick_propheT
источник
1

У меня была похожая проблема, это было вызвано MS UNIT Test DLL. Мое приложение WPF было скомпилировано как x86, но DLL модульного тестирования (файл EXE) как «Любой процессор». Я изменил DLL модульного теста, чтобы он был скомпилирован для x86 (так же, как EXE), и он был восстановлен.

user1257110
источник
0

Должен быть способ создания .NET EXE / DLL AnyCPU, и любые неуправляемые библиотеки DLL, от которых это зависит, скомпилированы как с x86, так и с x64, оба могут быть связаны с разными именами файлов, а затем модуль .NET динамически загружает правильный файл в зависимости от времени выполнения. архитектура процессора. Это сделало бы AnyCPU мощным. Если C ++ DLL поддерживает только x86 или x64, то AnyCPU, конечно, не имеет смысла. Но идея связывания, которую я пока не реализовал, поскольку диспетчер конфигурации даже не предоставляет средства для создания одного и того же проекта дважды с другой конфигурацией / платформой для множественного связывания, позволяя использовать AnyCPU или даже другие концепции, подобные любой конфигурации.

Грегори Морс
источник
2
добро пожаловать в stackoverflow! Вы можете попытаться сфокусировать / переформатировать этот ответ немного?
Корли Бригман
Это звучит так, как если бы это был хороший вопрос, или сообщение в блоге, или запрос функции в Connect ... на самом деле он не отвечает на этот вопрос.
Бен Фойгт
0

У меня было очень похожее предупреждение в моей сборке. Мои проекты были настроены на .NET 4.5, на сервере сборки был установлен Windows 8.1 SDK (для .NET 4.5.1). После обновления моих проектов до целевой .NET 4.5.1 (для меня это не было проблемой, было для совершенно нового приложения), я больше не получал предупреждение ...

NicoCV
источник
0

Я решил это предупреждение, изменив «Диспетчер конфигурации» на Выпуск (Смешанная Платформа).

Эду Пелайс
источник
0

Я получил это предупреждение в Visual Studio 2012 при компиляции задачи сценария конвейера SSIS SQL Server 2012 с пакетом обновления 1 (SP1) - до тех пор, пока не установил SQL Server 2012 с пакетом обновления 2 (SP2).

cdonner
источник
0

У меня была такая же проблема с открытием соединения SQLite, и использование Nuget и установка компонента, используемого в проекте (SQLite), исправили это! попробуйте установить свой компонент таким образом и проверьте результат

StudioX
источник