33

次のプロジェクト構造があります。

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 を使用するなど) を作成することも検討しましたが、まったくうまくいきませんでした。さらに、Visual Studio の標準の「ビルド」および「デバッグ」コマンドを通常どおりに動作させたいと考えています。


アップデート:

ここに私が何をしているかの詳細があります。

私はプロジェクトで解決策を持っていExecutableます。さらに、s と呼べるプロジェクトがたくさんありますPlugin。マネージド プロジェクト参照を介してExecutableこれらすべての を参照します。Plugin

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

これら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 Executable

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

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

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

更新 2

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

4

5 に答える 5

23

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

于 2012-12-05T01:22:04.000 に答える
5

編集:

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

-

コンテンツファイルではなく、埋め込みリソースを探している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;
}

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

于 2012-12-07T15:58:43.527 に答える
3

もう 1 つのオプションは、ContentFile を Library1 アセンブリ内のリソースとして埋め込み、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

于 2012-12-05T03:47:32.483 に答える