Visual Studioでビルドするときに条件付きで32/64ビット参照を使用する


124

32/64ビットでビルドし、対応する32/64ビットの依存関係があるプロジェクトがあります。構成を切り替えて正しい参照を使用できるようにしたいのですが、アーキテクチャに適した依存関係を使用するようにVisual Studioに指示する方法がわかりません。

たぶん私はこれについて間違った方法をとっていますが、構成ドロップダウンでx86とx64を切り替えることができて、参照されるDLLが正しいビットであるようにしたいと思います。


非常に不明確、これは何語ですか?DLLプロジェクトはソリューションにありますか?
ハンスパッサント

すみません、これは.NETです。私はC#で書いています。
ジョナサンイー

4
わかりました、私は愚かな解決策でそれを解決しました:x64 DLLのみを参照する追加のcsprojファイルを作成しました(そしてcsprojからx86構成を削除しました)。それは機能しますが、追加のcsprojを必要としないより洗練されたソリューションがある場合は、それを参照してください。
ジョナサンイー

回答:


99

これが以前のプロジェクトで私がやったことで、.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)プロジェクトのONLYターゲットプラットフォームを検討します
  • 現在のマシンに適切になるようにプラットフォーム決定ロジックを変更して、64ビットバイナリをビルド/参照して32ビットプラットフォームで実行しないようにします。

これはもともと社内のWiki用に作成されたものですが、詳細なステップバイステップの説明に興味がある場合は、変更してプロセス全体をブログに投稿しました。


1
いいね。以下の提案に従ってItemGroupで条件を使用しましたが、ここでは条件に$(PROCESSOR_ARCHITEW6432)と$(PROCESSOR_ARCHITECTURE)を使用しました。$(PROCESSOR_ARCHITECTURE)は32ビットと64ビットの両方のプラットフォームでx86を返すが、$(PROCESSOR_ARCHITEW6432)は64ビットでのみAMD64を返すことがわかりました。x86をテストする場合に注意すべき点(AMD64はx86の派生物であるためです)。
tjmoore 2013年

その情報をありがとう@tjmoore。どのO / Sでこれに気付きましたか?私はもう一度私の(Win7SP1)をチェックし、$(PROCESSOR_ARCHITECTURE)に対してAMD64と言っていますが、できる限り完全で完全な情報が欲しいです。
Hugo

7
おかしい、私の検索はここに私をもたらします、そして私はLeadToolsも使用しているのでこれが必要です... +1
Ed S.

ソリューションはデフォルトの構成で機能しますが、Visual Studio(私の場合は2012)のソリューション構成ドロップダウンリストの構成から構成を変更した場合は、私のテストでは機能しません。
サラウェインバーガー

$(PROCESSOR_ARCHITEW6432)を使用する代わりに、何らかの理由で$(PROCESSOR_ARCHITEW6432)が機能しなかったため、$(Platform)を使用しました。
Dzyann 2014

60

AFAIK、プロジェクトで32ビットまたは64ビット固有の参照(つまり、COM相互運用機能アセンブリ)が必要で、.csprojファイルを手動で編集する必要がない場合は、個別の32ビットと64ビットを作成する必要があります。 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/en-us/library/bb629388.aspx


すばらしい答え!! 私の日を救った!どうもありがとう。
hellodear 16

20

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

1
本当にありがとうございます!これは間違いなく受け入れられる解決策です!
ManicBlowfish 2016年

真剣に、この答えは受け入れられたものよりもはるかに優れて簡単です。
ヤンドロス

1
これを行った後、参照に重複したエントリがあるのは正常ですか?
natenho 2017年

7

プロジェクトの\ component \ v3_NET4などにあるx86 DLLを参照しています。x86 / x64用の特定のDLLは、「x86」および「x64」という名前のサブフォルダーにあります。

次に、$(PlatformName)に基づいて、適切なDLL(x86 / x64)を参照フォルダーにコピーするビルド前のスクリプトを使用しています。

xcopy /s /e /y "$(SolutionDir)..\component\v3_NET4\$(PlatformName)\*" "$(SolutionDir)..\component\v3_NET4"

私のために働く。


3

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

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

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

手順:

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

    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イベントハンドラーは必要ありません(プロセスアーキテクチャの評価-> x64 / x86から​​binフォルダーに対応するdllを移動します)。 -インストーラーでアーキテクチャを評価し、誤ったアーキテクチャのバイナリを削除して、正しいものをbinフォルダーに移動します。


2

私は同じ問題に直面し、まともな解決策を探すのにかなりの時間を費やしました。ほとんどの人はVisual Studioソリューションファイルの手動編集を提供しますが、これは非常に面倒でエラーが発生しやすく、後でこれらの編集済みファイルをVisual Studio GUIで探索するときに混乱します。私がすでにあきらめたとき、解決策はそれ自体で思いつきました。これは、Mickeが上記の回答で推奨しているものと非常によく似ています。

アカウントマネージャーでは、通常どおり、x86およびx64プラットフォーム用に2つの個別のビルドターゲットを作成しました。次に、x86アセンブリへの参照をプロジェクトに追加しました。この点で、私はプロジェクトがx86ビルド専用に構成されており、上記のHugoの提案に従って手動で編集しない限り、x64構成用にビルドされることはないと考えていました。

しばらくすると、私は最終的に制限を忘れてしまい、誤ってx64ビルドを開始しました。もちろん、ビルドは失敗しました。しかし、私が受け取ったエラーメッセージは重要でした。エラーメッセージで、参照したx86アセンブリとまったく同じ名前のアセンブリが、私のソリューションのx64ビルドターゲットとして意図されたフォルダーにないことが示されました。

これに気付いたので、適切なx64アセンブリをこのディレクトリに手動でコピーしました。栄光!x64ビルドが奇跡的に成功し、適切なアセンブリが見つかり、暗黙的にリンクされました。x64アセンブリのビルドターゲットディレクトリをこのフォルダーに設定するようにソリューションを変更するのはほんの数分でした。これらの手順の後、MSBuildファイルを手動で編集しなくても、x86とx64の両方のソリューションが自動的にビルドされます。

総括する:

  1. 1つのプロジェクトでx86およびx64ターゲットを作成する
  2. すべての適切なプロジェクト参照をx86アセンブリに追加する
  3. すべてのx64アセンブリに1つの共通ビルドターゲットディレクトリを設定します
  4. x64アセンブリの準備ができている場合は、x64ビルドターゲットディレクトリに1回コピーするだけです。

これらの手順が完了すると、ソリューションはx86とx64の両方の構成で正しくビルドされます。

これはVisual Studio 2010 .NET 4.0 C#プロジェクトで私のために働きました。明らかに、これはVisual Studioのドキュメント化されていない内部動作であり、2012、2013、2015バージョンで変更される可能性があります。誰かが他のバージョンを試してみる場合は、あなたの経験を共有してください。


-1

私は、Mickeの逆転のような、より簡単なソリューションと考えるものを使用することになりました。プロジェクトは、x86およびx64ターゲットを備えたC#フォームアプリであるVisual Studio 2015です。.NETアセンブリの1つを参照し、32ビットのものを使用しました。参照プロパティで、「ローカルコピー」をfalseに設定します。次に、適切な(32ビットまたは64ビット).Netアセンブリを各ターゲットディレクトリに手動で配置します。実際の参照ビット数は、外部インターフェイスを定義しているだけなので、同じ機能を持っているとは無関係です。空想を得たい場合は、ビルド後のコピーのステップを置くこともできます。このプロジェクトにもCOM参照があり、同じように機能することに注意してください。参照はオブジェクト/インターフェースを定義するため、参照DLLのビット数は無関係です。32ビットと64ビットの両方のCOM DLLが登録されている場合、アプリはレジストリの適切な場所を調べ、正しい32ビットまたは64ビットのCOMオブジェクトを作成します。私のために働く!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.