web-dev-qa-db-ja.com

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

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

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

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

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

  • エイリアス-グローバル
  • ローカルコピー-true
  • 文化 -
  • 説明-ASP.NETのエラーログモジュールとハンドラー(ELMAH)
  • ファイルの種類-アセンブリ
  • パス-D:\ webs\otherfolder\_myPath\___ tools\elmah\Elmah.dll
  • 解決済み-True
  • ランタイムバージョン-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)the elmah.dll is missing MyWebProject1のbinディレクトリ-ビルド自体には警告やエラーは含まれていません!

MyBaseProjectの.csprojに、値が「true」のprivate要素(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>

(プライベートタグは、デフォルトでは.csprojのxmlに表示されませんでしたが、Visual Studioは「ローカルコピー」をtrueに設定しましたが、「ローカルコピー」をfalseに変更-保存-そして再びtrueに設定-保存!)

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

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

263
toebens

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にのみ参照を持ち込みます。問題は、プロジェクト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);
    }
143
deadlydog

私はこのように対処します。参照のプロパティに移動して、これを実行します。

Set "Copy local = false"
Save
Set "Copy local = true"
Save

以上です。

Visual Studio 2010は、最初に参照タグに<private>True</private>を配置せず、「copy local」をfalseに設定すると、タグが作成されます。その後、それに応じてtrueとfalseに設定されます。

166
andrew

アセンブリをコードで直接使用していない場合、Visual Studioは有用であろうとする一方で、アセンブリが使用されていないことを検出し、出力に含めません。 Visual StudioとMSBuildの動作が異なるのはなぜかわかりません。両方のビルド出力を診断に設定して、結果を比較して、どこで分岐するかを確認できます。

コードで直接参照していない場合、elmah.dll参照については、プロジェクトにアイテムとして追加し、ビルドアクションをContentに設定し、出力ディレクトリにコピーをAlwaysに設定できます。

38
John Hunter

を見てみましょう:

私が始めたこのMSBuildフォーラムスレッド

私の一時的な解決策/回避策があります!

(MyBaseProjectは、elmah.dllからMyWebProject1のbinにコピーされるために、elmah.dllから(なんでも)いくつかのクラスを参照するコードを必要とします!)

14
toebens

同じ問題がありました。

プロジェクトのフレームワークバージョンが、参照するDLLのフレームワークバージョンと同じかどうかを確認します。

私の場合、私のクライアントは「Framework 4 Client」を使用してコンパイルされ、DLLは「Framework 4」にありました。

8
Andre Avelar

私が直面していた問題は、ライブラリプロジェクトに依存しているプロジェクトがあることでした。ビルドするために、私はこれらのステップに従っていました:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

それはもちろん、binにライブラリのdllファイルがなく、最も重要なのはパッケージのZipファイルにないことを意味していました。私はこれが完全に動作することを発見しました:

msbuild.exe myproject.vbproj /T:Rebuild;Package

なぜこの作業が行われたのか、そもそもなぜ機能しなかったのかはわかりません。しかし、それが役立つことを願っています。

6
vangorra

私はまったく同じ問題を抱えていましたが、同じソリューションの2つのプロジェクトがサードパーティライブラリの異なるバージョンを参照しているという事実が原因であることが判明しました。

すべての参照を修正したら、すべてが完全に機能しました。

4
Steven Engels

Alex Burtsevがコメントで言及したように、XAMLリソースディクショナリでのみ使用されるもの、または私の場合、XAMLでのみ使用され、コードビハインドでは使用されないものは、MSBuildでは「使用中」とは見なされません。

そのため、MSBuildがアセンブリが実際に使用されていることを確信させるために、いくつかのコードビハインドでアセンブリ内のクラス/コンポーネントへのダミー参照を単純に新規作成するだけで十分でした。

4
Scott

Deadlydogのスキームを使用して、

Y => X => A => B

私の問題は、Yをビルドしたとき、Xからのアセンブリ(AとB、15個すべて)がYのbinフォルダーに表示されないことでした。

Yから参照Xを削除し、保存、ビルドしてからX参照(プロジェクト参照)を再度追加し、保存、ビルドしてAとBがYのbinフォルダーに表示されることで解決しました。

3
J Z

ターゲットフレームワークを。NET Framework 4 Client Profileから。NET Framework 4に変更すると、この問題が修正されました。

したがって、例では、MyWebProject1のターゲットフレームワークを。NET Framework 4に設定します。

3
Fuyu Persimmon

これには、プロジェクトに.targetsファイルを追加し、プロジェクトのincludeセクションに含まれるように設定する必要があります。

手順については 私の答えはこちら をご覧ください。

2
Alex Essilfie

ビルド中に使用されないアセンブリを参照することは正しい習慣ではありません。ビルドファイルを追加して、追加ファイルをコピーする必要があります。ビルド後イベントを使用するか、プロパティグループを更新します。

他の投稿でいくつかの例を見つけることができます

2
verbedr

私は同じ問題を抱えていて、dllは動的にロードされる参照でした。この問題を解決するために、dllの名前空間で「使用」を追加しました。これで、dllが出力フォルダーにコピーされます。

2
Spamme

これが表示される別のシナリオは、Visual Studioで古い「Webサイト」プロジェクトタイプを使用している場合です。そのプロジェクトタイプの場合、自身のディレクトリ構造の外部にある.dllを参照できません(現在のフォルダーおよびダウン)。上記の答えで、ディレクトリ構造が次のようになっているとしましょう。

enter image description here

ProjectXとProjectYは親/子ディレクトリであり、ProjectXはB.dllを順に参照するA.dllを参照し、B.dllはルート(パッケージ)のNugetパッケージなどのディレクトリ構造外にあり、次にA. dllは含まれますが、B.dllは含まれません。

2
Focker

両方のプロジェクトが同じ.netバージョンであることを確認して、コピーローカルプロパティもチェックしますが、これはデフォルトでtrueである必要があります

0
john.kernel

今日も同様の問題がありましたが、これは間違いなくあなたの質問に対する答えではありません。しかし、私はすべての人に知らせたいと思います。そしておそらくsparkの洞察を提供したいと思います。

ASP.NETアプリケーションがあります。ビルドプロセスは、クリーニングしてからビルドするように設定されています。

2つの JenkinsCI スクリプトがあります。 1つは実稼働用、もう1つはステージング用です。アプリケーションをステージングにデプロイし、すべてが正常に機能しました。実稼働環境にデプロイされ、参照されたDLLファイルが欠落していました。このDLLファイルは、プロジェクトのルートにありました。 NuGetリポジトリにはありません。 DLLはdo not copyに設定されました。

CIスクリプトとアプリケーションは、2つの展開間で同じでした。ステージング環境でのクリーンとデプロイの後、ASP.NETアプリケーションのデプロイ場所(bin/)でDLLファイルが置き換えられました。これは、実稼働環境には当てはまりません。

このDLLファイルをbinディレクトリにコピーするためのステップをビルドプロセスに追加したテストブランチで判明しました。今、理解するのに少し時間がかかった部分。 CIプロセスはそれ自体をクリーニングしていませんでした。 DLLは作業ディレクトリに残り、誤ってASP.NET .Zipファイルにパッケージ化されていました。実稼働ブランチでは、DLLファイルが同じ方法でコピーされることはなく、これを誤って展開することもありませんでした。

TLDR;ビルドサーバーの動作を確認してください。

0
Jason Portnoy

よく似た問題に遭遇しました。 Visual Studio 2010を使用してコンパイルする場合、DLLファイルはbinフォルダーに含まれていました。ただし、MSBuildを使用してコンパイルする場合、サードパーティのDLLファイルは含まれませんでした。

とてもイライラします。私がそれを解決したのは、直接使用していないにもかかわらず、Webプロジェクトにパッケージへの NuGet 参照を含めることでした。

0
Gary Brunton