1. ホーム
  2. visual-studio

[解決済み】ソリューションでプロジェクトの依存関係を使用する場合、MSBuildは参照(DLLファイル)をコピーしない

2022-04-18 17:54:04

質問

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

  1. MyBaseProject <- このクラスライブラリは、サードパーティのDLLファイル(elmah.dll)を参照しています。
  2. MyWebProject1 <- このウェブアプリケーションプロジェクトは、MyBaseProjectへの参照を持っています。

私は、elmah.dll の参照を MyBaseProject Visual Studio 2008で、"参照の追加..." → "参照" タブ → "elmah.dll"を選択することにより行いました。

Elmah ReferenceのPropertiesは以下の通りです。

  • エイリアス - グローバル
  • ローカルにコピーする - true
  • カルチャー
  • 説明 - ASP.NET用エラーロギングモジュールとハンドラ(ELMAH)。
  • ファイルの種類 - アセンブリ
  • Path - D:\websotherfolder paragraph_myPath__toolselmah
  • 解決済み - True
  • ランタイムバージョン - v2.0.50727
  • 指定されたバージョン - false
  • 強い名前 - false
  • バージョン - 1.0.11211.0

MyWebProject1 プロジェクトMyBaseProjectへの参照は、以下の方法で追加しました。 参照を追加..." → "Projects" タブ → "MyBaseProject" を選択してください。このリファレンスのPropertiesは、以下のメンバを除いて同じです。

  • 説明
  • Path - D:\websCMS³³³³MyBaseProject³³Debug³³MyBaseProject.dll
  • バージョン - 1.0.0.0

でビルドを実行すると ビジュアルスタジオ elmah.dll ファイルは、私の MyWebProject1 の bin ディレクトリに、MyBaseProject.dll と共に格納されます。

しかし、クリーンアップして実行すると MSBuild for the solution (via D:\websCMS> C:¥WINDOWS¥Microsoft.NET¥Frameworkv3.5¥MSBuild.exe /t:ReBuild /p:Configuration=Debug MyProject.sln) その elmah.dll is missing を MyWebProject1 の bin ディレクトリにコピーしてください。

MyBaseProjectの.csprojにはすでに プライベート 要素に値 "true" を設定します (これは " のエイリアスのはずです)。 コピーローカル Visual Studio では ")。

<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では"copy local"がtrueとなっていましたが、デフォルトでは.csprojのxmlにprivateタグは表示されませんでした。をfalseに切り替えて保存し、再度trueに戻して保存しました!)

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

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

どうすればいいですか?

Visual StudioとMsBuildでビルドするときになぜ違うのかわかりませんが、MsBuildとVisual Studioでこの問題に遭遇したときの対処法を紹介します。

説明

アセンブリAはアセンブリBを参照しているので、プロジェクトXはAとBの両方への参照を含んでいます。また、プロジェクトXはアセンブリAを参照するコード(例えば、A.SomeFunction())を含んでいます。ここで、プロジェクト X を参照する新しいプロジェクト Y を作成します。

つまり、依存関係の連鎖は次のようになります。 Y => X => A => B

Visual Studio / MSBuild は賢く、プロジェクト X で必要だと検出された参照だけをプロジェクト Y に持っていこうとします。問題は、プロジェクト X には実際にはアセンブリ B を明示的に使用するコード (例: B.SomeFunction()) がないため、 VS/MSBuild は B が X で必要だとは検出せず、プロジェクト Y の bin ディレクトリにコピーせず、X と A アセンブリだけをコピーする点です。

解決方法

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

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

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

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

このような状況に遭遇したときに、私が通常追加するダミーコード("dummy code")のサンプルを以下に示します。

    // 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);
    }