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

StackOverflow https://stackoverflow.com/questions/145803

質問

Visual Studio ビルドをマルチターゲット用に設定する方法について、少しジレンマがあります。

背景:c# .NET v2.0 (サードパーティの 32 ビット DLL への p/invoking を含む)、SQL コンパクト v3.5 SP1、セットアップ プロジェクト。現時点では、プラットフォーム ターゲットは x86 に設定されているため、Windows x64 上で実行できます。

サードパーティ企業が DLL の 64 ビット バージョンをリリースしたばかりなので、専用の 64 ビット プログラムを構築したいと考えています。

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

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

2 つの別々のセットアップ プロジェクトを作成する必要があります (std.Visual Studio プロジェクト、Wix やその他のユーティリティは使用できません)、またはこれは同じ .msi 内で解決できますか?

あらゆるアイデアや提案を歓迎します。

役に立ちましたか?

解決

はい、同じプロジェクト内の同じコードベースで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の高度なインストーラは、関連する基本的なトリックを実行します(共通のMSI、および32ビットと64ビットの特定のMSIを作成し、.EXEセットアップランチャーを使用します)適切なバージョンを抽出し、実行時に必要な修正を行うため)

他のツールまたは WindowsインストーラーXML(WiX)ツールセットを使用して、おそらく同じ結果を達成できますが、 Advanced Installerは物事を非常に簡単にします(そしてその点で非常に手頃な価格です)ので、私は実際に代替を検討したことがありません。

高度なインストーラーを使用している場合でも、 がWiXを必要とする場合があるのは、.NETインストーラークラスのカスタムアクションです。特定のプラットフォームでのみ実行する特定のアクションを指定するのは簡単ですが(それぞれ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>

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

他のヒント

両方のプラットフォーム用にビルドした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は、選択したプラットフォームの正しいディレクトリを検索します。

あなたの質問に対する完全な答えはわかりませんが、 SQL Compact 3.5 SP1ダウンロードページ x64を見ているのを見る-役に立てば幸いです。

  

SQL Server Compactの変更による   SP1および追加の64ビットバージョン   サポート、集中インストールおよび混合   32ビットバージョンのモード環境   SQL Server Compact 3.5および64ビット   SQL Server Compact 3.5 SP1のバージョン   に見えるものを作成することができます   断続的な問題。最小化するには   競合の可能性、および可能にする   管理対象のプラットフォーム中立展開   クライアントアプリケーション、中央   64ビットバージョンのSQLのインストール   Server Compact 3.5 SP1を使用   Windows Installer(MSI)ファイルも   32ビットバージョンをインストールする必要があります   SQL Server Compact 3.5 SP1 MSIの例   ファイル。のみのアプリケーション用   ネイティブの64ビット、プライベートが必要   64ビットバージョンの展開   SQL Server Compact 3.5 SP1は   

私はこれを<!> quot; 32ビットSQLCEファイルを含める同様に 64bitファイル<!> quot;と読みます。 64ビットクライアント用に配布する場合。

人生を面白くする.. <!> quot;断続的な問題のように見えるもの<!> quot; line ...は<!> quot;のように聞こえますが、念のため、これを行います... <!> quot;

最後の質問について。ほとんどの場合、これを単一の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

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

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

詳細情報<!> amp;忍者が動き回る(基本的にこのシムの64ビットバージョンを使用するようにMSIを変更する)

Visual Studio 2005/2008でMSIを構築してSharePoint 64で動作する

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

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

プロジェクトファイルの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 依存関係を持つ 1 つの .Net ビルド

他のすべての回答では、プラットフォームに応じて異なるビルドを作成するための解決策が提供されていますが、私は「AnyCPU」構成のみを使用して、x86 および x64 DLL で動作するビルドを作成するオプションを提供します。

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

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

手順:

  1. csproj で AnyCPU を使用する
  2. csprojs で x86 DLL のみを参照するか x64 DLL のみを参照するかを決定します。UnitTests 設定を、選択したアーキテクチャ設定に適合させます。これは、VisualStudio 内でテストをデバッグ/実行するために重要です。
  3. 参照プロパティ設定時 ローカルにコピー & 特定のバージョン間違い
  4. この行を最初の行に追加して、アーキテクチャの警告を削除します。 プロパティグループ x86/x64 を参照するすべての csproj ファイル内:<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. このポストビルド スクリプトをスタートアップ プロジェクトに追加し、このスクリプトのパスを使用および変更して、すべての 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

    - >今すぐ申請を開始すると、アセンブリが見つからなかったという例外が得られます。

  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が開始時にDLLがバイナリフォルダーにコピーされることを保証する場合、AssemblyResolveイベントハンドラーは必要ありません(> x64/x86から​​Binフォルダーへの対応するDLLを移動します。間違ったアーキテクチャのバイナリを削除し、適切なアーキテクチャをビンフォルダーに移動します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top