web-dev-qa-db-ja.com

VisualStudioが間接的に参照されているプロジェクトからコンテンツファイルをコピーしない

私は次のプロジェクト構造を持っています:

_Library1 <--[project reference]-- Library2 <--[ref]-- Executable
--------                          --------            ----------
ContentFile                      .cs files           .cs files
.cs files
_

すべてのプロジェクト参照にはCopyLocal = trueがあります。

プロジェクトをビルドすると、ContentFileは_Library2_の出力ディレクトリにコピーされますが、Executableの出力ディレクトリにはコピーされません。つまり、実行可能ファイルにContentFileがない場合アプリケーションが実行されます。

コンテンツファイルが_Library2_の出力ディレクトリにコピーされているのに、Executableにはコピーされていないのはなぜですか?後者にもコピーする方法はありますか(人々はそれを忘れると確信しているので、ビルドイベントなしでそれを行いたいです)?

私は合理的で保守可能なソリューションを探しています。新しいプロジェクトまたはの新しい間接的に参照されるコンテンツファイルを追加するときに最小限の労力で済むため、単にそれを忘れることはほとんどありません。

ビルド後のイベントの使用(_xcopy ../Library/bin/Debug/SomeDll.dll bin/Debug_など)。プロジェクトの出力ディレクトリをデフォルト(プロジェクトごと)ではなく$(SolutionDir)/bin/...に手動で設定すると、どちらもすぐに大きな混乱になります。 「メインプロジェクト」にリンクとしてコンテンツファイルを追加するのも面倒でした。 C#の出力ファイルのデフォルト設定がVisual C++と同じ(つまり、_$SolutionDir/$Platform/$Configuration_)であれば問題ありませんが、そうではありません。

また、標準のMSBuildプロシージャをまったく使用せず、カスタムビルドターゲットを作成することも検討しました(Atmel Studioでgccを使用するなど)が、まったくうまくいきませんでした。さらに、VisualStudioの標準の「ビルド」コマンドと「デバッグ」コマンドを通常どおりに機能させたいと考えています。


更新:

これが私がしていることの詳細です。

Executableプロジェクトの解決策があります。さらに、Pluginsと呼ぶことができるプロジェクトがたくさんあります。 Executableは、管理対象プロジェクト参照を介して、これらすべてのPluginsを参照します。

プラグインプロジェクトは実行可能ファイルに合わせて調整されますが、再利用可能なコンポーネントが含まれる場合があるため、主な機能はExternalプロジェクトに実装されることが多く、Pluginプロジェクトは単なるラッパーのままです(常にではありません)。

上記のExternalプロジェクトでは、サードパーティが提供するネイティブDLLを使用する場合があります。これらのDLLは、コンテンツファイルとしてExternalプロジェクトに追加され、_Copy to output dir_が_Copy always_に設定されます。したがって、構造は上の図のようになります。

_External <---------------[is not aware of]--------------------+
--------                                                      |
.cs files <--[reference]-- PluginWrapper <--[reference]-- Executable
"Native DLL"               -------------                  ----------
                           .cs files                      .cs files
_

奇妙なことに、「ネイティブDLL」はExternalの出力ディレクトリ(明らかに)にコピーされますおよびPluginWrapper's、しかしないExecutable

開発者のワークフローは、完全に分離されたエンティティとして機能するExternalを作成することです(それらは頻繁に再利用されます)、ラップしますPluginWrapperを使用して、PluginWrapperへのプロジェクト参照のみをExecutableに追加します。これが明らかに非常に珍しいことであるのは奇妙だと思います。

ExecutableのMSBuildターゲットXMLを編集して(間接的に参照されるコンテンツファイルも含めるように)、問題を解決できたのではないかと思いました。

提案されているように、DLLを埋め込みリソースとしてプロジェクトに追加することを検討したいと思うかもしれませんが、そのようなネイティブDLLを埋め込むことは私には奇妙に思えます。結局、上の図から「[認識していない]」を削除し、プロジェクト参照をExternalに追加して開発者のワークフローを変更することは、Brenda Bellが提案したように、最も賢明な解決策かもしれません。理想的ではありません。

アップデート2

埋め込まれたリソースのアイデアがすべての場合に機能するとは限らないことに注意してください。実行可能ファイルのディレクトリ(cwdなどではない)に依存関係を配置する必要がある場合は、インストールフォルダーに管理者権限がないため(埋め込みリソースからファイルを解凍するため)、これが機能しない場合があります。奇妙に聞こえますが、これは私たちが使用していたサードパーティのライブラリの1つで深刻な問題でした。

32
dialer

Library1参照を実行可能プロジェクトに追加します。

21
Brenda Bell

編集:

すべてのコンテンツを別のプロジェクトに配置し、そのすべてのエントリを「コンテンツ」と「常にコピー」に設定して、外部および実行可能ファイルからそのプロジェクトを参照できます。

-

コンテンツファイルではなく、埋め込みリソースを探しているIMO。

ライブラリ1をコンパイルすると、コンテンツファイルはそのbinフォルダーに配置されます。ライブラリ2がコンパイルされると、コンパイラは参照されたコードを認識してそれを含めます(Library 1.dll)が、ライブラリ2のどこにも言及されていないため、コンテンツファイルは認識されません。ライブラリ2を実行可能ファイルにリンクする場合も同様です。

コンテンツファイルが比較的小さく(アイコン、テンプレートなど)、ソースコードを紛失した場合に編集する必要がないと思われる場合は、それらをリソースとして埋め込み、コンテンツを返すためのパブリックメソッドを提供できます。 :

 public static Stream GetResourceContent(string rName){
     string resName = System.Reflection.Assembly
         .GetExecutingAssembly().GetManifestResourceNames()
         .FirstOrDefault(rn => rn.EndsWith("."+rName));
    if(resName!=null)
        return System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resName);
    else
        return null;
}

テンプレートなどのコンテンツが変更される可能性がある場合は、実行可能プロジェクトにコピーを含めることを検討してください

5
Sten Petrov

もう1つのオプションは、ContentFileをLibrary1 Assembly内のリソースとして埋め込み、Assembly.GetManifestResource()を使用して抽出することです。

詳細については、次のリンクを参照してください。

http://www.attilan.com/2006/08/accessing-embedded-resources-using.html

http://blogs.msdn.com/b/alexdan/archive/2007/12/19/loading-embedded-resources-in-c-using-getmanifestresourcestream.aspx

3
MvdD

ブレンダの答えの1つのバリエーションは、Library1のコンテンツファイルを実行可能プロジェクトのリンクとして追加することです。プロジェクトにはまだエントリがありますが、各ファイルの複数のコピーを管理する必要はありません。

1
Chris Peach

XAMLファイルからのみLibrary1を参照している可能性があります。その場合、VisualStudioは使用法を認識しません。コードにも参照を追加します。例: name属性を適用する

0
Jens