ソリューションでプロジェクト依存関係を使用している場合、MSBuild は参照 (DLL ファイル) をコピーしません 質問する

ソリューションでプロジェクト依存関係を使用している場合、MSBuild は参照 (DLL ファイル) をコピーしません 質問する

Visual Studio ソリューションには 4 つのプロジェクトがあります (すべて .NET 3.5 をターゲットにしています)。私の問題では、次の 2 つだけが重要です。

  1. MyBaseProject <- このクラス ライブラリはサードパーティの DLL ファイル (elmah.dll) を参照します
  2. MyWebProject1 <- この Web アプリケーション プロジェクトには MyBaseProject への参照があります

Visual Studio 2008 で、「参照の追加...」→「参照」タブをクリックし、「elmah.dll」を選択して、MyBaseProjectに elmah.dll 参照を追加しました。

Elmah リファレンスのプロパティは次のとおりです。

  • エイリアス - グローバル
  • ローカルにコピー - true
  • 文化 -
  • 説明 - ASP.NET のエラー ログ モジュールとハンドラー (ELMAH)
  • ファイルタイプ - アセンブリ
  • パス - D:\webs\otherfolder\_myPath\__tools\elmah\Elmah.dll
  • 解決済み - 真
  • ランタイムバージョン - v2.0.50727
  • 指定されたバージョン - false
  • 厳密な名前 - false
  • バージョン - 1.0.11211.0

MyWebProject1で、「参照の追加...」→「プロジェクト」タブ→「MyBaseProject」を選択して、プロジェクト MyBaseProject への参照を追加しました。この参照のプロパティは、次のメンバーを除いて同じです。

  • 説明 -
  • パス - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
  • バージョン - 1.0.0.0

Visual Studioでビルドを実行すると、elmah.dll ファイルがMyBaseProject.dll とともにMyWebProject1 の binディレクトリにコピーされます。

ただし、ソリューションのMSBuild をクリーンアップして実行すると(D:\webs\CMS> C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /t:ReBuild /p:Configuration=Debug MyProject.sln 経由) 、ビルド自体には警告やエラーは含まれていないにもかかわらず、MyWebProject1 の bin ディレクトリにelmah.dll がありません。

MyBaseProject の .csproj に、値が "true" のプライベート要素が含まれていることは既に確認しています (これはVisual Studio の" copy local "のエイリアスになります)。

<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
    **<Private>true</Private>**
</Reference>

(Visual Studio では「ローカルにコピー」が true と表示されていましたが、デフォルトではプライベート タグは .csproj の xml に表示されませんでした。「ローカルにコピー」を false に切り替えて保存し、再度 true に設定して保存しました。)

MSBuild の何が問題なのでしょうか? (elmah.dll) 参照を MyWebProject1 の bin にコピーするにはどうすればよいですか?

すべてのプロジェクトの postbuild コマンドに postbuild コピー アクションを追加したくありません。(MyBaseProject に依存するプロジェクトが多数あると想像してください。)

ベストアンサー1

Visual Studio と MsBuild の間でビルドするときになぜ異なるのかはわかりませんが、MsBuild と Visual Studio でこの問題に遭遇したときに私が見つけたことは次のとおりです。

説明

サンプル シナリオとして、プロジェクト X、アセンブリ A、アセンブリ B があるとします。アセンブリ A はアセンブリ B を参照するため、プロジェクト X には A と B の両方への参照が含まれます。また、プロジェクト X にはアセンブリ A を参照するコード (例: A.SomeFunction()) が含まれます。ここで、プロジェクト X を参照する新しいプロジェクト Y を作成します。

依存関係のチェーンは次のようになります: Y => X => A => B

Visual Studio / MSBuild は、プロジェクト X で必要であると検出された参照のみをプロジェクト Y に持ち込むようスマートに動作します。これは、プロジェクト Y での参照汚染を回避するためです。問題は、プロジェクト X にはアセンブリ B を明示的に使用するコード (例: B.SomeFunction()) が実際には含まれていないため、VS/MSBuild は B が X で必要であることを検出せず、プロジェクト Y の bin ディレクトリにコピーしないことです。コピーされるのは、X アセンブリと A アセンブリのみです。

解決

この問題を解決するには 2 つのオプションがあり、どちらの場合もアセンブリ B がプロジェクト Y の bin ディレクトリにコピーされます。

  1. プロジェクト Y のアセンブリ B への参照を追加します。
  2. アセンブリ B を使用するプロジェクト X のファイルにダミー コードを追加します。

個人的には、いくつかの理由からオプション 2 を好みます。

  1. 将来、プロジェクト X を参照する別のプロジェクトを追加する場合、アセンブリ B への参照も含める必要があることを覚えておく必要はありません (オプション 1 の場合のように)。
  2. ダミー コードがなぜ必要で、削除してはいけないのかを明示的なコメントで説明できます。そのため、誰かが誤ってコードを削除した場合でも (未使用のコードを探すリファクタリング ツールなどを使用して)、ソース管理からそのコードが必要であることが簡単にわかり、復元できます。オプション 1 を使用し、誰かがリファクタリング ツールを使用して未使用の参照をクリーンアップした場合、コメントは表示されず、.csproj ファイルから参照が削除されたことだけが表示されます。

以下は、このような状況に遭遇したときに私が通常追加する「ダミー コード」のサンプルです。

    // DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
    private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
    {
        // Assembly A is used by this file, and that assembly depends on assembly B,
        // but this project does not have any code that explicitly references assembly B. Therefore, when another project references
        // this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
        // assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
        // gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
        var dummyType = typeof(B.SomeClass);
        Console.WriteLine(dummyType.FullName);
    }

おすすめ記事