32/64ビットでビルドし、対応する32/64ビットの依存関係があるプロジェクトがあります。構成を切り替えて正しい参照を使用できるようにしたいのですが、アーキテクチャに適した依存関係を使用するようにVisual Studioに指示する方法がわかりません。
たぶん私はこれについて間違った方法をとっていますが、構成ドロップダウンでx86とx64を切り替えることができて、参照されるDLLが正しいビットであるようにしたいと思います。
32/64ビットでビルドし、対応する32/64ビットの依存関係があるプロジェクトがあります。構成を切り替えて正しい参照を使用できるようにしたいのですが、アーキテクチャに適した依存関係を使用するようにVisual Studioに指示する方法がわかりません。
たぶん私はこれについて間違った方法をとっていますが、構成ドロップダウンでx86とx64を切り替えることができて、参照されるDLLが正しいビットであるようにしたいと思います。
回答:
これが以前のプロジェクトで私がやったことで、.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ターゲットプラットフォームを検討しますこれはもともと社内のWiki用に作成されたものですが、詳細なステップバイステップの説明に興味がある場合は、変更してプロセス全体をブログに投稿しました。
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
プロジェクトファイル内の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>
プロジェクトの\ 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"
私のために働く。
x86 / x64依存関係を持つ1つの.Netビルド
他のすべての答えは、プラットフォームに応じて異なるビルドを作成するためのソリューションを提供しますが、「AnyCPU」構成のみを使用して、x86およびx64 dllで動作するビルドを作成するオプションを提供します。
実行時の正しいx86 / x64-dllの解決
手順:
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
このポストビルドスクリプトをスタートアッププロジェクトに追加し、このスクリプトのパスを使用および変更して、ビルド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
->ここでアプリケーションを開始すると、アセンブリが見つからないという例外が発生します。
アプリケーションのエントリポイントの先頭に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;
}
利点:
欠点:-x86 / x64 dllが一致しない場合、コンパイル時にエラーが発生しません。-両方のモードでテストを実行する必要があります!
オプションで、ポストビルドスクリプトのCorflags.exeを使用して、x64アーキテクチャ専用の2番目の実行可能ファイルを作成します。
試してみる他のバリアント:-開始時にDLLがバイナリフォルダーにコピーされることを保証する場合は、AssemblyResolveイベントハンドラーは必要ありません(プロセスアーキテクチャの評価-> x64 / x86からbinフォルダーに対応するdllを移動します)。 -インストーラーでアーキテクチャを評価し、誤ったアーキテクチャのバイナリを削除して、正しいものをbinフォルダーに移動します。
私は同じ問題に直面し、まともな解決策を探すのにかなりの時間を費やしました。ほとんどの人はVisual Studioソリューションファイルの手動編集を提供しますが、これは非常に面倒でエラーが発生しやすく、後でこれらの編集済みファイルをVisual Studio GUIで探索するときに混乱します。私がすでにあきらめたとき、解決策はそれ自体で思いつきました。これは、Mickeが上記の回答で推奨しているものと非常によく似ています。
アカウントマネージャーでは、通常どおり、x86およびx64プラットフォーム用に2つの個別のビルドターゲットを作成しました。次に、x86アセンブリへの参照をプロジェクトに追加しました。この点で、私はプロジェクトがx86ビルド専用に構成されており、上記のHugoの提案に従って手動で編集しない限り、x64構成用にビルドされることはないと考えていました。
しばらくすると、私は最終的に制限を忘れてしまい、誤ってx64ビルドを開始しました。もちろん、ビルドは失敗しました。しかし、私が受け取ったエラーメッセージは重要でした。エラーメッセージで、参照したx86アセンブリとまったく同じ名前のアセンブリが、私のソリューションのx64ビルドターゲットとして意図されたフォルダーにないことが示されました。
これに気付いたので、適切なx64アセンブリをこのディレクトリに手動でコピーしました。栄光!x64ビルドが奇跡的に成功し、適切なアセンブリが見つかり、暗黙的にリンクされました。x64アセンブリのビルドターゲットディレクトリをこのフォルダーに設定するようにソリューションを変更するのはほんの数分でした。これらの手順の後、MSBuildファイルを手動で編集しなくても、x86とx64の両方のソリューションが自動的にビルドされます。
総括する:
- 1つのプロジェクトでx86およびx64ターゲットを作成する
- すべての適切なプロジェクト参照をx86アセンブリに追加する
- すべてのx64アセンブリに1つの共通ビルドターゲットディレクトリを設定します
- x64アセンブリの準備ができている場合は、x64ビルドターゲットディレクトリに1回コピーするだけです。
これらの手順が完了すると、ソリューションはx86とx64の両方の構成で正しくビルドされます。
これはVisual Studio 2010 .NET 4.0 C#プロジェクトで私のために働きました。明らかに、これはVisual Studioのドキュメント化されていない内部動作であり、2012、2013、2015バージョンで変更される可能性があります。誰かが他のバージョンを試してみる場合は、あなたの経験を共有してください。
私は、Mickeの逆転のような、より簡単なソリューションと考えるものを使用することになりました。プロジェクトは、x86およびx64ターゲットを備えたC#フォームアプリであるVisual Studio 2015です。.NETアセンブリの1つを参照し、32ビットのものを使用しました。参照プロパティで、「ローカルコピー」をfalseに設定します。次に、適切な(32ビットまたは64ビット).Netアセンブリを各ターゲットディレクトリに手動で配置します。実際の参照ビット数は、外部インターフェイスを定義しているだけなので、同じ機能を持っているとは無関係です。空想を得たい場合は、ビルド後のコピーのステップを置くこともできます。このプロジェクトにもCOM参照があり、同じように機能することに注意してください。参照はオブジェクト/インターフェースを定義するため、参照DLLのビット数は無関係です。32ビットと64ビットの両方のCOM DLLが登録されている場合、アプリはレジストリの適切な場所を調べ、正しい32ビットまたは64ビットのCOMオブジェクトを作成します。私のために働く!