在同一个解决scheme/项目中,用Visual Studio将32位和64位都瞄准

我有一个关于如何build立我的视觉工作室build立多目标的困境。

背景:带有一个安装项目的p#调用第三方32位DLL,SQL compact v3.5 SP1的c#.NET 2.0版本。 目前,平台目标设置为x86,因此可以在Windows x64上运行。

第三方公司刚刚发布了他们的DLL的64位版本,我想build立一个专用的64位程序。

这提出了一些问题,我还没有得到答案。 我想要有完全相同的代码库。 我必须build立对32位DLL或64位DLL的引用。 (第三方和SQL Server Compact)

这可以解决与2套新的configuration(Debug64和Release64)?

我必须创build2个独立的安装项目(标准视觉工作室项目,没有维克斯或任何其他实用工具),或者可以在同一个.msi内解决?

任何想法和/或build议将受到欢迎。

是的,您可以在同一个项目中使用相同的代码库来定位x86和x64。 一般情况下,如果你在VS.NET中创build正确的解决schemeconfiguration,事情就会正常工作(尽pipeP / Invoke到完全不受pipe理的DLL很可能需要一些条件代码):我发现需要特别注意的项目是:

  • 引用外部pipe理程序集具有相同的名称,但它们自己的特定位(这也适用于COM互操作程序集)
  • MSI软件包(正如已经提到的那样,它将需要以x86或x64为目标)
  • MSI包中的任何自定义.NET Installer基于类的操作

程序集引用问题不能在VS.NET中完全解决,因为它只允许你给一个项目添加一个给定名字的引用。 要解决此问题,请手动编辑项目文件(在VS中,右键单击解决scheme资源pipe理器中的项目文件,select“卸载项目”,然后再次右键单击并select“编辑”)。 在添加了一个对程序集x86版本的引用之后,你的项目文件将包含如下内容:

<Reference Include="Filename, ..., processorArchitecture=x86"> <HintPath>C:\path\to\x86\DLL</HintPath> </Reference> 

将该引用标签包裹在ItemGroup标签中,指出其适用的解决schemeconfiguration,例如:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <Reference ...>....</Reference> </ItemGroup> 

然后,复制并粘贴整个ItemGroup标记,并对其进行编辑以包含64位DLL的详细信息,例如:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' "> <Reference Include="Filename, ..., processorArchitecture=AMD64"> <HintPath>C:\path\to\x64\DLL</HintPath> </Reference> </ItemGroup> 

在VS.NET中重新加载你的项目后,Assembly Reference对话框会被这些改变弄糊涂了,你可能会遇到一些有关错误目标处理器的程序集的警告,但是所有的构build都可以正常工作。

解决MSI的问题接下来,不幸的是,这需要一个非VS.NET工具:我喜欢Caphyon的高级安装程序的目的,因为它拉开了涉及的基本技巧(创build一个共同的MSI,以及32位和64位特定的MSI,并使用.EXE安装启动程序来提取正确的版本,并在运行时进行必要的修正)非常非常好。

使用其他工具或Windows安装程序XML(WiX)工具集可能会达到相同的结果,但是高级安装程序使事情变得如此简单(而且相当实惠),我从来没有真正考虑过替代scheme。

有一点你可能仍然需要使用WiX,即使在使用高级安装程序时,也适用于.NET Installer Class自定义操作。 虽然指定某些只能在特定平台上运行的操作(分别使用VersionNT64和Not VersionNT64执行条件)很简单,但即使在64位机器上,内置的AI自定义操作也将使用32位Framework执行。

这可能会在将来的版本中得到修复,但是现在(或者在使用不同的工具来创build具有相同问题的MSI时),您可以使用WiX 3.0的托pipe自定义操作支持来创build具有适当位数的操作DLL将使用相应的框架执行。


编辑:从版本8.1.2,高级安装程序正确支持64位自定义操作。 自从我原来的答案,它的价格已经增加了很多,不幸的是,虽然它仍然是非常好的价值,相比InstallShield和其他…


编辑:如果你的DLL是在GAC中注册的,你也可以这样使用标准引用标签(以SQLite为例):

 <ItemGroup Condition="'$(Platform)' == 'x86'"> <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" /> </ItemGroup> <ItemGroup Condition="'$(Platform)' == 'x64'"> <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64" /> </ItemGroup> 

条件也可以归结为所有的构buildtypes,发布或debugging,只是指定处理器体系结构。

假设您有为这两个平台构build的DLL,它们位于以下位置:

 C:\whatever\x86\whatever.dll C:\whatever\x64\whatever.dll 

你只需要编辑你的.csproj文件:

 <HintPath>C:\whatever\x86\whatever.dll</HintPath> 

对此:

 <HintPath>C:\whatever\$(Platform)\whatever.dll</HintPath> 

然后,您应该能够针对两个平台构build项目,并且MSBuild将在所选平台的正确目录中查找。

不知道你的问题的总体答案 – 但我想我会指出在SQL Compact 3.5 SP1下载页面的附加信息部分看到你正在看x64的评论 – 希望它有帮助。

由于SQL Server Compact SP1和其他64位版本支持的更改,32位版本的SQL Server Compact 3.5和64位版本的SQL Server Compact 3.5 SP1的集中安装和混合模式环境可以创build看起来是间歇性的问题。 为最大限度地减less冲突的可能性并启用托pipe客户端应用程序的平台中立部署,使用Windows Installer(MSI)文件集中安装64位版本的SQL Server Compact 3.5 SP1还需要安装32位版本的SQL Server紧凑型3.5 SP1 MSI文件。 对于只需要本地64位的应用程序,可以使用64位版本的SQL Server Compact 3.5 SP1的专用部署。

如果分配给64位客户端,我将其读作“包含32位SQLCE文件以及 64位文件”。

让我觉得有趣的生活..必须说,我喜欢“什么似乎是间歇性的问题”行…听起来有点像“你想象的东西,但以防万一,这样做…”

关于你的最后一个问题。 很可能你无法解决这个单一的MSI内。 如果你正在使用registry/系统文件夹或任何相关的东西,MSI本身必须知道这一点,你必须准备一个64位的MSI,以正确安装在32位机器上。

有一种可能性,你可以让你的产品作为一个32应用程序安装,仍然能够使其运行64位一,但我认为可能有点难以实现。

被说,我认为你应该能够保持一切代码基地。 在我目前的工作场所,我们设法这样做了。 (但它确实花了一些杂耍,使一切发挥)

希望这可以帮助。 下面是一些有关32/64位问题的链接: http : //blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

如果您使用.NET编写的自定义操作作为MSI安装程序的一部分,那么您有另一个问题。

运行这些自定义动作的'shim'总是32bit,那么你的自定义动作也会运行32bit,尽pipe你指定了什么目标。

更多的信息和一些忍者移动(基本上改变微星使用这个垫片的64位版本)

在Visual Studio 2005/2008中构buildMSI以使用SharePoint 64

使用Visual Studio进行64位托pipe自定义操作

您可以生成两个不同的解决scheme,然后合并它们! 我为VS 2010做了这个工作。 我有两个不同的CMake生成的解决scheme,我将它们合并

您可以使用项目文件中的dll引用的ItemGroup条件。
这将导致Visual Studio在您更改活动configuration时重新检查条件和引用。
只需为每个configuration添加一个条件。

例:

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