webdevqa.jp.net

同じソリューション/プロジェクトでVisual Studioを使用して32ビットと64ビットの両方をターゲットにする

マルチターゲット向けにビジュアルスタジオビルドをセットアップする方法については、少しジレンマがあります。

背景:サードパーティの32ビットDLL、SQLコンパクトv3.5 SP1を呼び出し、セットアッププロジェクトを使用したc#.NET v2.0。現在、プラットフォームターゲットはx86に設定されているため、Windows x64で実行できます。

サードパーティの会社はDLLの64ビットバージョンをリリースしたばかりで、専用の64ビットプログラムを作成したいと思います。

これにより、まだ答えが得られていないいくつかの質問が発生します。まったく同じコードベースが必要です。 32ビットDLLのセットまたは64ビットDLLのいずれかを参照してビルドする必要があります。 (サードパーティとSQL Server Compactの両方)

これは、2つの新しい構成セット(Debug64およびRelease64)で解決できますか?

2つの個別のセットアッププロジェクト(std。visual studioプロジェクト、Wixまたはその他のユーティリティなし)を作成する必要がありますか、または同じ.msi内で解決できますか?

どんなアイデアや提案も歓迎します。

109

はい、同じプロジェクトの同じコードベースでx86とx64の両方をターゲットにできます。一般的に、VS.NETで適切なソリューション構成を作成すればうまくいきます(ただし、完全に管理されていないDLLに対するP/Invokeには、いくつかの条件付きコードが必要になる可能性が高いです)。

  • 同じ名前であるが独自の特定のビット数を持つ外部マネージアセンブリへの参照(これはCOM相互運用機能アセンブリにも適用されます)
  • MSIパッケージ(既に述べたように、x86またはx64を対象とする必要があります)
  • MSIパッケージ内のカスタム.NETインストーラークラスベースのアクション

アセンブリ参照の問題は、VS.NET内で完全に解決することはできません。指定した名前の参照をプロジェクトに追加できるのは1回だけです。これを回避するには、プロジェクトファイルを手動で編集します(VSでは、ソリューションエクスプローラーでプロジェクトファイルを右クリックし、[プロジェクトのアンロード]を選択してから、もう一度右クリックして[編集]を選択します)。たとえば、アセンブリの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でプロジェクトをリロードした後、これらの変更によって[アセンブリ参照]ダイアログが少し混乱し、間違ったターゲットプロセッサのアセンブリに関する警告が表示される場合がありますが、すべてのビルドは正常に機能します。

MSIの問題の解決は次の段階であり、残念ながらこれは 意志 VS.NET以外のツールが必要です:Caphyonの Advanced Installer を使用すると、関連する基本的なトリック(32ビットおよび64ビット固有の一般的なMSIを作成する) MSI、および.EXEセットアップランチャーを使用して適切なバージョンを抽出し、実行時に必要な修正を行います)。

他のツールまたは Windows Installer XML(WiX)ツールセット を使用しても同じ結果を得ることができますが、Advanced Installerを使用すると非常に簡単に(しかも非常に手頃な価格で)見たことがありません代替案。

一つのこと 五月 ただし、Advanced Installerを使用している場合でも、.NET Installer Classカスタムアクション用にWiXが必要です。特定のプラットフォームでのみ実行する特定のアクションを指定することは簡単ですが(それぞれVersionNT64およびNOT VersionNT64実行条件を使用)、組み込みのAIカスタムアクションは、64ビットマシン上でも32ビットフレームワークを使用して実行されます。

これは将来のリリースで修正される可能性がありますが、現時点では(または同じツールを使用して同じ問題のあるMSIを作成する場合)、WiX 3.0のマネージカスタムアクションサポートを使用して、適切なビット数のアクションDLLを作成できます対応するフレームワークを使用して実行されます。


編集:バージョン8.1.2以降、Advanced Installerは64ビットのカスタムアクションを正しくサポートします。私の最初の回答以来、残念ながら、InstallShieldとそのilkに比べると非常に良い値ですが、価格はかなり高くなっています...


編集: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>

また、条件はすべてのビルドタイプ(リリースまたはデバッグ)に縮小され、プロセッサアーキテクチャを指定するだけです。

81
mdb

両方のプラットフォーム用にビルドされた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>

その後、両方のプラットフォームをターゲットにプロジェクトをビルドできるはずです。MSBuildは、選択したプラットフォームの正しいディレクトリを検索します。

27
Tim Booker

あなたの質問に対する完全な答えはわかりませんが、 SQL Compact 3.5 SP1ダウンロードページ の追加情報セクションでコメントを指摘すると思いました。

SQL Server Compact SP1の変更および追加の64ビットバージョンのサポートにより、32ビットバージョンのSQL Server Compact 3.5および64ビットバージョンのSQL Server Compact 3.5 SP1の集中インストールおよび混在モード環境では、断続的に見えるものが作成される可能性があります問題。競合の可能性を最小限に抑え、管理されたクライアントアプリケーションのプラットフォームニュートラル展開を有効にするには、Windowsインストーラー(MSI)ファイルを使用してSQL Server Compact 3.5 SP1の64ビットバージョンを一元的にインストールするには、SQL Serverの32ビットバージョンもインストールする必要がありますコンパクトな3.5 SP1 MSIファイル。ネイティブ64ビットのみを必要とするアプリケーションの場合、SQL Server Compact 3.5 SP1の64ビットバージョンのプライベート展開を利用できます。

64ビットクライアント用に配布する場合、「32ビットSQLCEファイルおよび64ビットファイルを含める」と読みます。

人生を面白くします。「断続的な問題のように見える」ラインが大好きだと言わざるを得ません。

1
gleng

プロジェクトファイルの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>
0
Yochai Timmer

x86/x64依存関係を持つ1つの.Netビルド

他のすべての回答は、プラットフォームに応じて異なるビルドを作成するソリューションを提供しますが、「AnyCPU」構成のみを持ち、x86およびx64 dllで動作するビルドを作成するオプションを提供します。

このための配管コードを作成する必要があります。 app.configでこれを機能させることができませんでした。他の誰かがapp.configを介してそれを解決する方法を知っているなら、私は本当に知りたいです。

実行時の正しいx86/x64-dllの解像度

手順:

  1. CsprojでAnyCPUを使用する
  2. Csprojsでx86またはx64 dllのみを参照するかどうかを決定します。 UnitTests設定を、選択したアーキテクチャ設定に適合させます。 VisualStudio内でテストをデバッグ/実行するために重要です。
  3. Reference-PropertiesでCopy Local特定のバージョン to false
  4. X86/x64を参照するすべてのcsprojファイルの最初のPropertyGroupに次の行を追加して、アーキテクチャの警告を取り除きます:_<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>_
  5. このポストビルドスクリプトをスタートアッププロジェクトに追加し、ビルドbin\x86\bin\x64 \の対応するサブフォルダーにあるすべてのx86/x64 dllをコピーするこのスクリプトspのパスを使用および変更します。

    xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86 xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64

    ->今すぐアプリケーションを起動すると、アセンブリが見つからないという例外が発生します。

  6. アプリケーションエントリポイントの最初に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;
    }
    _
  7. 単体テストがある場合、AssemblyInitializeAttributeを持つメソッドでTestClassを作成し、そこに上記のTryResolveArchitectureDependency-Handlerを登録します。 (Visual Studio内で単一のテストを実行する場合、これは時々実行されません。UnitTestビンからではなく参照が解決されます。したがって、ステップ2の決定は重要です。)

利点:

  • 両方のプラットフォームに1つのインストール/ビルド

欠点:-x86/x64 dllが一致しない場合、コンパイル時にエラーが発生しません。 -両方のモードでテストを実行する必要があります!

必要に応じて、ポストビルドスクリプトでCorflags.exeを使用して、x64アーキテクチャ専用の2番目の実行可能ファイルを作成します。

試してみる他のバリアント:-開始時にDLLがバイナリフォルダーにコピーされることを保証する場合、AssemblyResolveイベントハンドラーは必要ありません(プロセスアーキテクチャを評価する->対応するdllをx64/x86から​​binフォルダーに移動して戻す)。 -インストーラーでアーキテクチャを評価し、間違ったアーキテクチャのバイナリを削除し、正しいフォルダーをbinフォルダーに移動します。

0
Felix Keil

.NETで記述されたカスタムアクションをMSIインストーラーの一部として使用する場合、別の問題が発生します。

これらのカスタムアクションを実行する「シム」は常に32ビットであり、指定したターゲットに関係なく、カスタムアクションも32ビットで実行されます。

詳細情報といくつかの忍者の動き(回避するには基本的にMSIを変更してこのシムの64ビットバージョンを使用します)

SharePoint 64で動作するようにVisual Studio 2005/2008でMSIを構築する

Visual Studioでの64ビットのマネージカスタムアクション

0
Ryan

最後の質問について。ほとんどの場合、これを単一のMSI内で解決することはできません。レジストリ/システムフォルダまたは関連するものを使用している場合、MSI自体がこれを認識している必要があり、32ビットマシンに適切にインストールするために64ビットMSIを準備する必要があります。

製品を32 itアプリケーションとしてインストールし、それでも64ビット1として実行できる可能性がありますが、それを達成するのは少し難しいかもしれません。

そうは言っても、すべてに対して単一のコードベースを維持できるはずだと思います。私の現在の職場では、そうすることができました。 (しかし、すべてを一緒にプレイするにはジャグリングが必要でした)

お役に立てれば。 32/64ビットの問題に関連する情報へのリンクは次のとおりです。 http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

0
Lior Friedman

2つのソリューションを別々に生成し、後でマージできます!私はVS 2010でこれを行いました。それは動作します。 CMakeによって生成された2つの異なるソリューションがあり、それらをマージしました

0
voidMainReturn