我有一个构建在32/64位并且具有相应的32/64位依赖项的项目。我希望能够切换配置并使用正确的引用,但是我不知道如何告诉Visual Studio使用适合于体系结构的依赖关系。
也许我会采用错误的方式,但是我希望能够在配置下拉菜单中在x86和x64之间切换,并使引用的DLL正确无误。
我有一个构建在32/64位并且具有相应的32/64位依赖项的项目。我希望能够切换配置并使用正确的引用,但是我不知道如何告诉Visual Studio使用适合于体系结构的依赖关系。
也许我会采用错误的方式,但是我希望能够在配置下拉菜单中在x86和x64之间切换,并使引用的DLL正确无误。
Answers:
这是我在上一个项目中所做的,这需要.csproj文件的手动版本。您还需要为不同的二进制文件(理想情况下是彼此的兄弟姐妹)提供单独的目录,并与目标平台使用相同的名称。
将单个平台的引用添加到项目后,在文本编辑器中打开.csproj。在<ItemGroup>
元素中的第一个元素之前<Project>
,添加以下代码,这将有助于确定您正在运行(和构建)的平台。
<!-- Properties group for Determining 64bit Architecture -->
<PropertyGroup>
<CurrentPlatform>x86</CurrentPlatform>
<CurrentPlatform Condition="'$(PROCESSOR_ARCHITECTURE)'=='AMD64' or '$(PROCESSOR_ARCHITEW6432)'=='AMD64'">AMD64</CurrentPlatform>
</PropertyGroup>
然后,针对特定于平台的参考,进行如下更改:
<ItemGroup>
<Reference Include="Leadtools, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.dll</HintPath>
</Reference>
<Reference Include="Leadtools.Codecs, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.Codecs.dll</HintPath>
</Reference>
<Reference Include="Leadtools.ImageProcessing.Core, Version=16.5.0.0, Culture=neutral, PublicKeyToken=9cf889f53ea9b907, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.ImageProcessing.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Entity" />
<!-- Other project references -->
</ItemGroup>
注意$(CurrentPlatform)
上面定义的属性的使用。您可以改为使用条件,以便将哪个程序集包括在哪个平台中。您可能还需要:
$(PROCESSOR_ARCHITEW6432)
并$(PROCESSOR_ARCHITECTURE)
与$(Platform)
只考虑项目的目标平台我最初是为内部Wiki写这篇文章的,但是,如果您对详细的分步说明感兴趣,我已经对其进行了修改并将整个过程发布到我的博客中。
AFAIK,如果您的项目需要特定于32位或64位的引用(即COM-interop程序集),并且您对手动编辑.csproj文件没有兴趣,则必须创建单独的32位和64位项目。
我应该注意以下解决方案未经测试,但应该可以。如果您愿意手动编辑.csproj文件,那么您应该能够通过单个项目获得所需的结果。.csproj文件只是一个MSBuild脚本,因此,有关完整参考,请参见此处。在编辑器中打开.csproj文件后,找到<Reference>
元素。您应该能够将这些元素分成3个不同的项目组:不是平台特定的引用,特定于x86的引用和特定于x64的引用。
这是一个示例,假定您的项目配置有名为“ x86”和“ x64”的目标平台
<!-- this group contains references that are not platform specific -->
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<!-- any other references that aren't platform specific -->
</ItemGroup>
<!-- x86 specific references -->
<ItemGroup Condition=" '$(Platform)' == 'x86' ">
<Reference Include="MyComAssembly.Interop">
<HintPath>..\..\lib\x86\MyComAssembly.Interop.dll</HintPath>
</Reference>
<!-- any additional x86 specific references -->
</ItemGroup>
<!-- x64 specific referneces -->
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
<Reference Include="MyComAssembly.Interop">
<HintPath>..\..\lib\x64\MyComAssembly.Interop.dll</HintPath>
</Reference>
<!-- any additional x64 specific references -->
</ItemGroup>
现在,当您将项目/解决方案构建配置设置为以x86或x64平台为目标时,每种情况下都应包含适当的引用。当然,您需要使用这些<Reference>
元素。您甚至可以设置虚拟项目,在其中添加x86和x64引用,然后将<Reference>
那些虚拟项目文件中的必要元素复制到“真实”项目文件中。
编辑1
这是指向常见MSBuild项目项的链接,我无意中将其从原始帖子中删除:http : //msdn.microsoft.com/zh-cn/library/bb629388.aspx
您可以对项目文件中dll引用的ItemGroup使用条件。
每当您更改活动配置时,这将导致Visual Studio重新检查条件和引用。
只需为每个配置添加一个条件。
例:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Reference Include="DLLName">
<HintPath>..\DLLName.dll</HintPath>
</Reference>
<ProjectReference Include="..\MyOtherProject.vcxproj">
<Project>{AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT}</Project>
<Name>MyOtherProject</Name>
</ProjectReference>
</ItemGroup>
具有x86 / x64依赖关系的一个.Net构建
尽管所有其他答案都为您提供了一个根据平台进行不同构建的解决方案,但我为您提供了一个选项,使其仅具有“ AnyCPU”配置,并构建可与x86和x64 dll一起使用的构建。
在运行时解析正确的x86 / x64-dll
脚步:
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
将此postbuild脚本添加到启动项目中,使用和修改此脚本的路径,以便将所有x86 / x64 dll复制到构建bin \ x86 \ bin \ x64 \的相应子文件夹中
xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86
xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64
->当您现在启动应用程序时,会出现一个例外,即找不到程序集。
在应用程序入口点的开头立即注册AssemblyResolve事件
AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
使用此方法:
/// <summary>
/// Event Handler for AppDomain.CurrentDomain.AssemblyResolve
/// </summary>
/// <param name="sender">The app domain</param>
/// <param name="resolveEventArgs">The resolve event args</param>
/// <returns>The architecture dependent assembly</returns>
public static Assembly TryResolveArchitectureDependency(object sender, ResolveEventArgs resolveEventArgs)
{
var dllName = resolveEventArgs.Name.Substring(0, resolveEventArgs.Name.IndexOf(","));
var anyCpuAssemblyPath = $".\\{dllName}.dll";
var architectureName = System.Environment.Is64BitProcess ? "x64" : "x86";
var assemblyPath = $".\\{architectureName}\\{dllName}.dll";
if (File.Exists(assemblyPath))
{
return Assembly.LoadFrom(assemblyPath);
}
return null;
}
好处:
缺点:-当x86 / x64 dll不匹配时,在编译时没有错误。-您仍应在两种模式下都进行测试!
(可选)使用postbuild脚本中的Corflags.exe创建x64体系结构专用的第二个可执行文件
可以尝试使用的其他变体:-如果确保在启动时将dll复制到二进制文件夹中,则不需要AssemblyResolve事件处理程序(评估流程体系结构->将相应的dll从x64 / x86移至bin文件夹,然后再移回。) -在Installer中评估架构,并删除错误架构的二进制文件,然后将正确的二进制文件移至bin文件夹。
我遇到了同样的问题,花了相当长的时间寻找一个不错的解决方案。大多数人都提供对Visual Studio解决方案文件的手动编辑,这在以后在Visual Studio GUI中浏览这些编辑后的文件时非常繁琐,容易出错并且令人困惑。当我已经放弃时,解决方案本身就来了。这与Micke在上面的答案中建议的非常相似。
与往常一样,在客户经理中,我为x86和x64平台创建了两个单独的构建目标。接下来,我在项目中添加了对x86程序集的引用。在这一点上,我相信该项目仅针对x86构建进行配置,并且永远不会针对x64配置进行构建,除非我按照上述Hugo的建议对其进行手动编辑。
一段时间后,我最终忘记了限制,并意外地开始了x64构建。当然,构建失败了。但是重要的是我收到的错误消息。错误消息告诉我,与我的参考x86程序集完全相同的程序集在我的解决方案的x64构建目标文件夹中丢失。
注意到这一点之后,我将正确的x64程序集手动复制到了该目录中。荣耀!我的x64构建奇迹般地成功了,并找到了正确的程序集并进行了隐式链接。只需几分钟即可修改我的解决方案,以将x64程序集的构建目标目录设置为此文件夹。完成这些步骤后,无需为MSBuild文件进行任何手动编辑即可自动为x86和x64构建解决方案。
总结一下:
- 在单个项目中创建x86和x64目标
- 将所有正确的项目引用添加到x86程序集
- 为所有x64程序集设置一个通用的构建目标目录
- 如果您已经准备好x64程序集,只需将它们复制一次到x64构建目标目录中
完成这些步骤后,您的解决方案将针对x86和x64配置正确构建。
这在Visual Studio 2010 .NET 4.0 C#项目上对我有用。显然,这是Visual Studio的一种未记录的内部行为,在2012、2013和2015版本中可能会发生变化。如果有人会尝试其他版本,请分享您的经验。
我最终使用了我认为更简单的解决方案,类似于Micke的解决方案。该项目是C#表单应用程序Visual Studio 2015,具有x86和x64目标。我引用了一个.NET程序集,我使用了32位程序集。在参考属性中,将“复制本地”设置为false。然后,我只需在每个目标目录中手动放置适当的(32或64位).Net程序集。假设它们具有相同的功能,则实际的参考位数无关紧要,因为它只是定义外部接口。如果您想花哨的话,也可以放置构建后复制步骤。请注意,该项目也有一个COM参考,同样的工作原理。该参考定义了对象/接口,因此参考DLL的位无关紧要。如果同时注册了32位和64位COM DLL,该应用程序将在注册表中的适当位置查找并创建正确的32或64位COM对象。为我工作!