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


273

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

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

私はへelmah.dll参照を追加MyBaseProjectをクリックして、Visual Studio 2008で「参照の追加...」→「参照」タブ→「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 )elmah.dllが 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>

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

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

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


11
なぜこれが起こるのかについて、より明確な答えが欲しいです。
David Faivre


1
完全なソースコードサンプルが機能する最終的なソリューションはありますか?
Kiquenet 2013年

2
@deadlydogによる以下の回答stackoverflow.com/a/21055664/21579を参照してください。優れた説明と私のための問題の解決...以下の最も投票された答えはVS2012には正しくありません。
Jeff Widmer

回答:


153

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

4
ここで議論されていないのは、Webプロジェクトの/ binにあるビルド製品のコピーと、ターゲット出力ディレクトリ(例:/ bin / x86 / Debug)へのルーチンのコピーに違いがあるということです。前者はビルド時に参照プロジェクトによって実行され、後者は依存するWebプロジェクトによって実行されます。Microsoft.Common.targetsを調べると、これを理解するのに役立ちます。web / binへのコピーは、ローカルのコピー動作にまったく依存しません。Debugを介して実行されているCassiniによって参照される構造の一部ではない、出力ターゲットディレクトリへのコピーに対するローカルの影響をコピーします。
user1164178 14

6
msbuildではなく「ダミーコード」を追加せずにVSで機能した理由を説明できますか?
toebens

3
関数を呼び出すよりも侵襲性が低いため、アセンブリ内に含まれるクラスのタイプをダミー変数に割り当てることができます。Type dummyType = typeof(AssemblyA.AnyClass);
Arithmomaniac 2015年

14
Visual Studioで[コードの最適化]設定をオンにしない限り、上記のソリューション#2は機能します。その場合でも、dllは除外されます。「最適化」を上書きするために、もう1行追加しました。 Console.WriteLine(dummyType.FullName);
JasonG 2015

3
ソリューション2はVisual Studio 2017では機能しませんでした。最初に考えたのは、アセンブリXでenumfrom B のみを使用していて、列挙型がインライン化されていると想定していたためです。Bからの型を直接使用するコードを追加しましたが、役に立ちませんでした。また、私のXがBのサブクラス型であるAの型を使用する場合も常にそうでした。そのため、コンパイラーがBがXに必要ではなく、無視できると考える方法を理解することはできません。これはばかげています。
Xharlie

170

私はそれをこのように扱うだけです。参照のプロパティに移動して、これを実行します。

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

以上です。

Visual Studio 2010は最初に次のもの<private>True</private> を配置しません。 参照タグに「ローカルのコピー」をfalseに設定すると、タグが作成されます。その後、それをtrueとfalseに設定します。


10
これは天の恵みでした。これありがとう!
レベッカ

22
MSBuild 4 / VS2012では動作しませんでした。つまり、参照を更新して言うことができましたが、<Private>true</Private>MSBuildには影響がないようです。最後に、NuGet参照をダウンレベルプロジェクトに追加しました。
Michael Teper 2013年

2
私のために働いていませんでした。それでも、System.Net.Http.Formattingはbinフォルダーにコピーされません。
山本章

4
これはと同等でHave you tried turning it off and on again?、うまくいきました!
グアノメ2014年

6
VS2015は引き続き同じように動作します。「ローカルのコピー」を「False」に設定してから、参照されている.dllで「True」に戻すと、機能します。
2015

38

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

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


3
Elmahがコードで使用されていない場合、出力ディレクトリのコメントへのコピーの+1は、コンテンツとしてコピーすることに意味があります。
キットは

4
実際、使用されていないアセンブリは無視されますが、VS 2010では、XAMLリソースディクショナリでアセンブリを使用することは、VSによるassmeblyの使用とは見なされないため、コピーされません。
Alex Burtsev、2011年


これは、dllが必要な単体テストプロジェクトに適しています。テストを実行するためだけにメインプロジェクトが必要としないDLLを追加したくありません。
Lukos

14

を見てみましょう:

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

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

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


1
くそー-これは私がやってきた唯一の解決策です-それを行うためのより良い方法があるかもしれないと思っていました!
ニックスプーン2013

2
ハックの少ないソリューション(違反なし)については、以下の
アンドリュー

1
今この時にお探しの方のために、toebens'答え MSDNには、本質的に同じであるdeadlydogの答え何年か後に提供します、。
jpaugh

8

私も同じ問題を抱えていました。

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

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


6

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

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

もちろん、それは私がビンに、そして最も重要なことにパッケージのzipファイルに私のライブラリのdllファイルが欠落していたことを意味しました。私はこれが完璧に機能することを発見しました:

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

なぜこれがうまくいったのか、なぜそもそもうまくいかなかったのか、私にはわかりません。しかし、それが役に立てば幸いです。


TeamCityの/ t:Buildを使用してソリューション全体をビルドするのと同じ問題が1つのステップで発生し、次の/ t:Package on WebAPIプロジェクトで発生しました。プロジェクト参照によって参照されるDLLは含まれていません。これは上記を使用して修正されました-WebAPIの/ T:Rebuild; PackageにそれらのDLLが含まれていました。
アンディホイル2017

5

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

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


4

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

そのため、一部のコードビハインドでアセンブリ内のクラス/コンポーネントへのダミー参照を新しく追加するだけで、アセンブリが実際に使用されていることをMSBuildに納得させることができました。


これはまさに私の問題であり、うまくいった解決策でした。これを理解しようとするのに時間がかかりすぎました。Scott&@Alex Burstevに感謝
カロル

良い悲しみ、これは私を夢中にさせた。はい、私はFontAwesome.WPFを使用しており、XAML内からのみでした(明らかな理由による)。ダミーメソッドを追加すると役立ちました。ありがとう!私はバグを提出したので、はい、VS 2017 15.6はまだ、影響を受けている:github.com/dotnet/roslyn/issues/25349
ソレンKuklau

3

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

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


3

デッドリードッグのスキームを使用して、

Y => X => A => B

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

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


他の多くの解決策を何時間も検索して試した後、これは私にとってはうまくいきました。
Suncat2000 2017

2

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



2

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

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


2

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

ここに画像の説明を入力してください

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


0

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

ASP.NETアプリケーションがあります。ビルドプロセスがクリーンに設定されてからビルドされます。

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

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

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

TLDR; ビルドサーバーが何を実行しているかを確認してください。


0

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


0

Visual Studio 2015を使用して追加のパラメーターを追加する

/ deployonbuild = false

msbuildコマンドラインに問題を修正しました。


-1

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

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


これはトップアンサーの複製です。
Giles Roberts

-3

特に依存関係の注入を使用している場合は、プロジェクト参照からのすべての参照DLLファイルをWebサイトプロジェクトに含めることは必ずしも良い考えではありません。Webプロジェクトは、具体的な実装DLLではなく、インターフェイスDLLファイル/プロジェクトへの参照を追加するだけです。ファイル。

参照を実装DLLファイル/プロジェクトに直接追加する場合、開発者がインターフェイス経由ではなく実装DLLファイル/プロジェクトの具象クラスで「新規」を呼び出すのを防ぐことができないためです。また、実装を使用するためにWebサイトに「ハードコード」を記述しているのです。

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