我是 Visual Studio 2010 中项目配置的新手,但我已经完成了一些 research,但仍然无法完全解决这个问题。我有一个带有引用 C# DLL 的 C++ DLL 的 Visual Studio 解决方案。 C# DLL 引用了一些其他 DLL,一些在我的项目中,一些在外部。当我尝试编译 C++ DLL 时,我收到以下警告:
警告 MSB3270:正在构建的项目的处理器架构“MSIL”与参考“[internal C# dll]”、“x86”的处理器架构不匹配。
它告诉我去配置管理器来调整我的架构。 C# DLL 设置为平台目标 x86。如果我尝试将其更改为其他内容,例如 Any CPU,它会抱怨,因为它所依赖的外部 DLL 之一具有平台目标 x86。
当我查看配置管理器时,它将我的 C# DLL 的平台显示为 x86,将我的 C++ 项目的平台显示为 Win32。这似乎是正确的设置;当然,我不希望我的 C++ 项目的项目将平台设置为 x64,这是唯一的其他选项。
我在这里做错了什么?
这个警告似乎是在新的 Visual Studio 11 Beta 和 .NET 4.5 中引入的,尽管我认为它以前可能是可能的。
首先,这实际上只是一个警告。如果您只是处理 x86 依赖项,它不应该有任何伤害。当您声明您的项目与“任何 CPU”兼容但您依赖于 x86 或 x64 的项目或 .dll 程序集时,Microsoft 只是试图警告您。因为您有 x86 依赖项,所以从技术上讲,您的项目与“任何 CPU”不兼容。要使警告消失,您实际上应该将项目从“任何 CPU”更改为“x86”。这很容易做到,这里是步骤。
转到构建|配置管理器菜单项。在列表中找到您的项目,在 Platform 下它会显示“Any CPU” 从下拉列表中选择“Any CPU”选项,然后选择
这将使警告消失,并表明您的程序集或项目现在不再与“任何 CPU”兼容,但现在特定于 x86。如果您正在构建具有 x64 依赖项的 64 位项目,这也适用;您只需选择 x64 即可。
另请注意,如果项目是纯 .NET 项目,通常可以与“任何 CPU”兼容。仅当您引入针对特定处理器架构的依赖项(第 3 方 dll 或您自己的 C++ 托管项目)时,才会出现此问题。
这是一个非常顽固的警告,虽然它是一个有效的警告,但在某些情况下,由于使用 3rd 方组件和其他原因,它无法解决。我有一个类似的问题,除了警告是因为我的项目平台是 AnyCPU 并且我正在引用为 AMD64 构建的 MS 库。顺便说一下,这是在 Visual Studio 2010 中,似乎是通过安装 VS2012 和 .Net 4.5 引入的。
由于我无法更改我引用的 MS 库,并且我知道我的目标部署环境将永远是 64 位,所以我可以放心地忽略这个问题。
警告呢? Microsoft 在回复 a Connect report 时发布了一个选项是禁用该警告。只有非常了解您的解决方案架构并且您完全了解您的部署目标并且知道这在开发环境之外并不是真正的问题时,您才应该这样做。
您可以编辑项目文件并添加此属性组和设置以禁用警告:
<PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
一个好的经验法则是“打开 DLL,关闭 EXE”,即:
EXE 通过指定 x86 或 x64 以操作系统为目标。
DLL 保持打开状态(即 AnyCPU),因此它们可以在 32 位或 64 位进程中实例化。
当您将 EXE 构建为 AnyCPU 时,您所做的就是将决定使用哪个进程位数的决定推迟到操作系统,这将使 EXE 按自己的喜好进行 JIT。也就是说,x64 操作系统将创建一个 64 位进程,x86 操作系统将创建一个 32 位进程。
将 DLL 构建为 AnyCPU 使它们与任一进程兼容。
有关程序集加载的详细信息,请参阅 here。执行摘要的内容如下:
AnyCPU – 根据调用进程加载为 x64 或 x86 程序集
x86 – 加载为 x86 程序集;不会从 x64 进程加载
x64 – 加载为 x64 程序集;不会从 x86 进程加载
C# DLL 设置为平台目标 x86
这是一个问题,DLL实际上并不能选择进程的位数。这完全由 EXE 项目决定,这是第一个加载的程序集,因此它的平台目标设置是计算和设置进程位数的那个。
DLL 没有选择,它们需要与进程位数兼容。如果它们不是,那么当您的代码尝试使用它们时,您将得到一个带有 BadImageFormatException 的大 Kaboom。
因此,DLL 的一个很好的选择是 AnyCPU,因此它们可以以任何方式工作。这对 C# DLL 很有意义,它们确实可以工作。但可以肯定的是,不是您的 C++/CLI 混合模式 DLL,它包含非托管代码,只有当进程在 32 位模式下运行时才能正常工作。您可以让构建系统生成有关此的警告。这正是你得到的。只是警告,它仍然可以正常构建。
只是解决问题。将 EXE 项目的平台目标设置为 x86,它不会与任何其他设置一起使用。并且只需将所有 DLL 项目保存在 AnyCPU 上。
我得到了同样的警告,我这样做了:
卸载项目编辑项目属性即.csproj 添加以下标签:
我今天遇到了这个问题,只是查看 Visual Studio 中的构建配置并没有帮助,因为它显示了未构建的项目和引用的项目的任何 CPU。
然后我查看了引用项目的 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 似乎没有看到它。
从引用的项目中删除这一行解决了我的问题。
将 Directory.Build.props 文件添加到您的解决方案文件夹
将其粘贴到其中:
<Project>
<PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
</Project>
如果您的 C# DLL 具有基于 x86 的依赖项,那么您的 DLL 本身将必须是 x86。我真的没有办法解决这个问题。 VS 抱怨将其更改为(例如)x64,因为 64 位可执行文件无法加载 32 位库。
我对 C++ 项目的配置有点困惑。为构建提供的警告消息表明它针对 AnyCPU,因为它报告它针对的平台是 [MSIL],但您指出该项目的配置实际上是 Win32。本机 Win32 应用程序不应涉及 MSIL - 尽管如果它与 C# 库交互,它可能需要启用 CLR 支持。所以我认为在信息方面存在一些差距。
我能否恭请您查看并发布项目的确切配置以及它们如何相互关联的更多细节?如果可能的话,很乐意提供进一步的帮助。
除了 David Sacks 的回答之外,您可能还需要转到 Project Properties
的 Build
选项卡,并将 Platform Target
设置为 x86
,以便为您提供这些警告的项目。尽管您可能希望如此,但此设置似乎与配置管理器中的设置并不完全同步。
对于 C# 项目,x86 的目标就像它听起来的那样。它说这个程序集只支持 x86 架构。对于 x64 也是如此。另一方面,任何 CPU 都表示我不在乎哪种架构,我都支持。那么,接下来的 2 个问题是(1)使用这些 dll 的可执行文件的配置是什么? (2) 你的操作系统/计算机的位数是多少?我问的原因是因为如果您的可执行文件被编译为以 64 位运行,那么它也需要所有依赖项才能在 64 位模式下运行。您的 Any CPU 程序集应该能够被加载,但也许它引用了一些只能在 x86 配置中运行的其他依赖项。如果您计划在 64 位模式下运行可执行文件,请检查所有依赖项和依赖项的依赖项,以确保一切都是“任何 CPU”或“x64”。否则,你会有问题。
在许多方面,Visual Studio 并不容易编译任何 CPU 和各种依赖于体系结构的程序集的混合体。这是可行的,但它通常要求必须为 x86 和 x64 分别编译一个原本是“任何 CPU”的程序集,因为某处的某些依赖项有两个版本。
我之前也遇到过类似的问题,特别是在向现有 x64 解决方案(如 SharePoint)添加测试解决方案时。就我而言,这似乎与某些项目模板默认添加为某些平台这一事实有关。
这是通常对我有用的解决方案:在配置管理器中将所有内容设置为正确的平台(活动配置下拉菜单,通常说调试,是一个很好的方法)和项目平台(在项目属性中),然后构建,然后将所有内容设置回 AnyCPU。有时我必须删除并重新添加一些依赖项(每个项目的属性中的 DLL),有时必须更改“在 32 位或 64 位进程中运行测试”(双击 Local.testsettings 并转到主机)。
在我看来,这只是设置一些东西然后将其设置回去,但幕后可能还有更多我没有看到的事情。不过,它在过去对我来说相当一致。
对于我的项目,我需要能够构建到 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"/>
我有类似的问题,它是由 MS UNIT Test DLL 引起的。我的 WPF 应用程序编译为 x86,但单元测试 DLL(引用的 EXE 文件)为“任何 CPU”。我更改了要为 x86 编译的单元测试 DLL(与 EXE 相同),它已被重新处理。
由于 f.csproj 是基于命令构建的,因此您可能还会收到 MS Fakes 程序集的此警告,该程序集不容易解决。幸运的是the Fakes xml allows you to add it in there。
我的构建中有一个非常相似的警告。我的项目设置为面向 .NET 4.5,在构建服务器上安装了 Windows 8.1 SDK(用于 .NET 4.5.1)。在将我的项目更新为 .NET 4.5.1 之后(对我来说这不是问题,是一个全新的应用程序),我不再收到警告......
我解决了这个警告,将“配置管理器”更改为发布(混合平台)。
编译 SQL Server 2012 SP1 SSIS 管道脚本任务时,我在 Visual Studio 2012 中收到此警告 - 直到我安装了 SQL Server 2012 SP2。
我在 SQLite 打开连接时遇到了同样的问题,并且使用 Nuget 并安装了项目中使用的组件(SQLite)修复了它!尝试以这种方式安装您的组件并检查结果
只想为那些在这里找不到答案的人发帖解决了他们的问题。
运行应用程序时,请确保正确设置了解决方案平台下拉菜单。我的在 x86 上,这反过来又导致了我这个问题。
应该有一种方法可以制作 .NET EXE/DLL AnyCPU,以及它所依赖的任何非托管 DLL,它们都使用 x86 和 x64 编译,可能都捆绑了不同的文件名,然后 .NET 模块根据其运行时动态加载正确的处理器架构。这将使 AnyCPU 功能强大。如果 C++ DLL 只支持 x86 或 x64,那么 AnyCPU 当然是没有意义的。但是捆绑这两个想法我还没有看到实现,因为配置管理器甚至没有提供一种方法来两次构建同一个项目,使用不同的配置/平台进行多次捆绑,从而允许 AnyCPU 甚至其他概念(如任何配置)成为可能。