2008-09-28 130 views
103

我有一個困境,關於如何設置我的Visual Studio構建多目標。針對32位和64位與Visual Studio在同一解決方案/項目

背景:c#.NET v2.0與p /調用到第三方32位DLL,SQL compact v3.5 SP1,帶有安裝項目。 現在,平臺目標被設置爲x86,因此它可以在Windows x64上運行。

第三方公司剛剛發佈了它們的DLL的64位版本,我想構建一個專用的64位程序。

這提出了一些問題,我還沒有得到答案。 我想要有完全相同的代碼庫。 我必須建立對32位DLL或64位DLL的引用。 (第三方和SQL Server Compact)

這可以通過2套新配置(Debug64和Release64)解決嗎?我是否必須創建2個獨立的安裝項目(標準視覺工作室項目,沒有Wix或任何其他實用工具),或者這可以在相同的.msi內解決嗎?

任何想法和/或建議將受到歡迎。

+0

@Magnus·約翰遜:你可以用兩種配置來完成一半的目標。 MSI有點困難。 – user7116 2008-09-28 13:33:26

回答

80

是的,你可以針對x86和x64的,在同一個項目相同的代碼庫。我發現需要特別注意的項目是:

一般來說,如果您創建VS.NET的解決方案的配置(雖然P/Invoke來完全託管DLL將最有可能需要一些有條件的代碼)的東西會只是工作
  • 引用具有相同的名稱,但其自身特定位數外管理組件(這也適用於COM互操作程序集)
  • MSI軟件包(正如已經指出的,將需要針對x86或x64)
  • MSI包中的任何基於.NET Installer類的自定義操作

程序集引用問題無法在VS.NET中完全解決,因爲它只允許您將具有給定名稱的引用添加到項目中。要解決此問題,請手動編輯項目文件(在VS中,右鍵單擊解決方案資源管理器中的項目文件,選擇Unload Project,然後再次右鍵單擊並選擇編輯)。添加一個參考,比如說,組件的x86版本後,你的項目文件將包含類似:

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

換行引用的ItemGroup標籤內的標籤,表明它適用於解決方案配置,如:

<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對話框會被這些改變弄糊塗了,並且你可能會遇到一些有關錯誤目標處理器的程序集警告,但是所有的構建都可以正常工作。

解決MSI問題是旁邊,不幸的是這需要non-VS.NET工具:我喜歡Caphyon的Advanced Installer用於這一目的,因爲它拉了所涉及的基本技巧(創建一個共同的微星,如以及32位和64位特定的MSI,並使用.EXE安裝啓動器來提取正確的版本,並在運行時進行必要的修正)非常非常好。

您可以使用其他工具或Windows Installer XML (WiX) toolset可能達到同樣的效果,但先進的安裝程序使事情那麼容易(而且是相當實惠的那個),我從來沒有真正看的替代品。你可能仍然需要維克斯因爲雖然,採用先進的安裝程序,即使

一件事,就是你的.NET安裝類自定義操作。儘管指定僅應在特定平臺上運行的某些操作(分別使用VersionNT64和Not VersionNT64執行條件)很簡單,但即使在64位機器上,內置的AI自定義操作也將使用32位框架執行。

這可能會在將來的版本中修復,但現在(或使用不同的工具創建具有相同問題的MSI時),可以使用WiX 3.0的託管自定義操作支持來創建動作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> 

該條件也降低到所有生成類型,釋放或調試,只是指定的處理器體系結構。

+0

在Visual Studio 2008中,我發現 s不能嵌套。一旦我將新的設置在的其餘部分之下,該解決方案就可以正常工作。我也必須將x86更改爲AnyCPU,這可能與我的特定項目的歷史有關。 – 2010-10-01 06:25:40

+0

高級安裝程序看起來非常棒。 – Pat 2010-11-05 22:37:41

1

不確定你的問題的總體回答 - 但我想我會指出SQL Compact 3.5 SP1 download page的附加信息部分中的評論,看到你正在看x64 - 希望它有幫助。

由於SQL Server精簡 SP1和 SQL Server壓縮3.5和64位 SQL版本的32位版本更改的其他64位版本 支持,集中安裝和混合 模式環境服務器緊湊3.5 SP1 可以創建似乎是 間歇性問題。爲了儘量減少衝突的 潛力,並能夠管理 客戶端應用程序的 平臺無關的部署,集中 安裝使用 Windows安裝程序(MSI)文件還 的SQL Server精簡3.5 SP1的64位版本需要安裝SQL Server Compact 3.5 SP1 MSI 文件的32位版本 。對於只有 需要64位版本的本機64位,私有 部署的應用程序,可以使用SQL Server Compact 3.5 SP1的 。

我看這是「包括32位SQLCE文件以及 64位檔案」如果分配64位客戶。

讓我覺得生活很有意思..我必須說,我喜歡「似乎是間歇性問題」的線...聽起來有點像「你在想象的東西,但以防萬一,這樣做......」

0

關於你最後一個問題。很可能你無法在單個MSI中解決這個問題。 如果您正在使用註冊表/系統文件夾或任何相關的東西,MSI本身必須知道這一點,並且您必須準備一個64位MSI以在32位機器上正確安裝。

有一種可能性,你可以讓你的產品安裝爲一個32應用程序,仍然能夠使其運行64位,但我認爲這可能有點難以實現。

這是說我認爲你應該能夠保持一切代碼基地。在我目前的工作場所,我們設法這樣做了。 (但它確實花了一些雜耍,使一切發揮)

希望這可以幫助。 繼承人鏈接到一些信息與32/64位的問題: http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

26

比方說,你有這些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> 

然後,您應該能夠建立您的項目針對這兩個平臺,以及MSB uild將查找所選平臺的正確目錄。

0

您可以採用不同產生兩個解決方案和合並他們之後! 我爲VS 2010做了這個,並且它工作正常。我不得不CMake的生成2個不同的解決方案,我合併他們

0

您可以使用一個的ItemGroup的條件在項目文件中的DLL引用。
無論何時更改活動配置,這將導致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>