.NET CoreプロジェクトでNuGet参照をビルド出力にコピーするにはどうすればよいですか?


108

.NET Coreを使用してプラグインシステムを作成しようとしています。私の要件の1つは、プラグインDLLとその依存関係をインストールのためにユーザーに配布できることです。

ただし、dotnet publishハッキングとして使用しなくても、NuGet依存関係をビルドアーティファクトとして含めてビルドフォルダーに出力する方法を理解できません。これを.csprojファイル(プロジェクトファイル)で指定できる方法はありますか?


2
なぜdotnet publishハッキングなのでしょうか?コマンドをビルド後のスクリプトとしてcsprojファイルに含めます。
オースティンドレンスキー2017年

3
dotnet publish私はプラグインを作成しているため、フレームワーク全体をpublishフォルダーにスローします。フレームワークはすでにブートストラッププログラムによってロードされているため、ファイルの大部分は不要です。.NET Frameworkでのビルドの動作に似たものを探しています。
chyyran 2017年

そして、<CopyToOutputDirectory>Always</CopyToOutputDirectory>移動したい各dllのcsprojに含めるとうまくいきませんか?おそらく<link>ノードと組み合わせる?
オースティンドレンスキー2017年

7
<PackageReference/>はサポートしていません<CopyToOutputDirectory>
chyyran 2017年

1
「全体の枠組み」かかわらNuGetから来て...とあなたがビルド出力に、すべてのNuGetアセンブリをコピーするに選ぶならば、あなたはそれらのすべてを取得します...
マーティン・ウルリッヒ

回答:


177

これを<PropertyGroup>csprojファイル内に追加して、NuGetアセンブリをビルド出力に強制的にコピーできます。

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

ただし、ビルド出力(bin/Release/netcoreapp*/*)は移植可能および配布可能ではないことに注意してくださいdotnet publish。しかし、あなたの場合、アセンブリをビルド出力にコピーすることは、おそらくテスト目的で非常に役立ちます。ただし、DependencyContextAPIを使用して、ローカルディレクトリを列挙する代わりに、アプリケーションの依存関係グラフの一部であるDLLとその場所を解決することもできます。


7
Nuget DLLだけでなく、すべてのDLLをコピーします
Mohammad Dayyan 2017

2
コア2すべてのMicrosoft DLLも取得しています。なぜだかわかりませんが、NuGetのみを入手する前に、それをやめましたか?迷惑
Piotr Kula 2017

4
@MartinUllrich詳細について教えてくださいDependencyContext。アプリケーションディレクトリにないDLLを見つけるにはどうすればよいですか?とにかくそれはどこですか?
ygoe 2017年

2
asp.netコアがSystem.ValueTuple.dllをコピーしないので私にとっては機能しません
Ali Yousefi

1
.netフレームワークプロジェクトの@AliYousefie system.valuietupleは、最近の.netフレームワークバージョンおよびビルドツールのNuGetから提供されなくなりました
Martin Ullrich

10

PostBuildEventを使用して、ビルド時のモジュールのデプロイメントを自動化できます。

ビルドフォルダーでNuGetアセンブリを取得するには、モジュールのcsprojに追加します

<PropertyGroup>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>

インクルード/エクスクルードを使用して、必要なモジュールファイルを定義します(必要に応じてパスを変更します)

<ItemGroup>
    <ModuleFiles
      Include="$(TargetDir)*.dll"
      Exclude="$(TargetDir)System*.dll;$(TargetDir)Microsoft*.dll"
      DestinationPath="$(SolutionDir)src\MyProject\Modules\MyModule\%(Filename)%(Extension)">
    </ModuleFiles>
</ItemGroup>

ビルドフォルダーをデフォルトにリセットし、PostbuildEventを追加します

<Target Name="PublishModule" AfterTargets="PostBuildEvent" Inputs="@(ModuleFiles)" Outputs="@(ModuleFiles->'%(DestinationPath)')">
    <WriteLinesToFile File="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
    <Copy SourceFiles="@(ModuleFiles)" DestinationFiles="@(ModuleFiles->'%(DestinationPath)')" />
    <Delete Files="$(SolutionDir)src\[YOURAPP]\app_offline.htm" />
</Target>

使用中のファイルのエラーを回避するために、すでに実行されているアプリをリサイクルするためにapp_offlineを含めています。


私のプロジェクトでは、私は「Microsoft.Extensions.Logging.Log4Net.AspNetCore」Nugetライブラリへの依存性を持っており、それがNetCoreの一部ではありませんので、このアプローチは動作しません
sad_robot

4

追加

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

動作しませんでしたが、これをFramework .csprojファイルに追加します。

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

した。


これは、.Net Framework 4.7.2プロジェクト内から.net Standard 2.0ライブラリを参照しているときにうまく機能しました。他には何も修正していません。
Grungondola

3

私はこれをより簡単な方法で "解決"(回避策を作成)しました。

ビルド後

dotnet publish "$(ProjectFileName)" --no-build -o pub
xcopy "$(ProjectDir)pub\3rdPartyProvider.*.dll" "$(OutDir)"

pub 公開したものをステージングするためのフォルダです

注:使用しているバージョンによってdotnet.exeは、コマンドを使用--no-buildできない場合があります。

たとえば、v2.0.3では使用できません。そしてv2.1.402で利用可能です。VS2017 Update4にはv2.0.3が含まれていました。そしてUpdate8には2.1.xがあります

更新:

上記の設定は基本的なデバッグ環境で機能しますが、それをビルドサーバー/実稼働環境に配置するには、さらに多くのものが必要です。私が解決しなければならないこの特定の例ではRelease|x64Release|x86個別にビルドします。それで私は両方を説明しました。しかし、ビルド後のdotnet publishコマンドをサポートするために、最初RuntimeIdentifierにプロジェクトファイルに追加しました。

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
  <OutputPath>..\..\lib\</OutputPath>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
  <OutputPath>..\..\lib\</OutputPath>
  <RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>

なぜ私はそれを必要とし、なぜあなたはそれなしで逃げることができるのですか?私はこれが必要だったのでビルドプログラムが警告MSB3270をインターセプトし、表示された場合はビルドを失敗させるように設定されて。この警告は、「ねえ、あなたの依存関係のいくつかのファイルは間違ったフォーマットです」と言います。しかし、この演習の目標を覚えていますか?パッケージ依存DLLをプルする必要があります。そして、多くの場合、次のポストビルドは気にしないので、この警告が存在するかどうかは重要ではありません。繰り返しますが、これは気にかける私のビルドプログラムです。だから、私は追加しましたRuntimeIdentifierため、本番ビルドで使用する2つの構成しました。

フルポストビルド

if not exist "$(ProjectDir)obj\$(ConfigurationName)" mkdir "$(ProjectDir)obj\$(ConfigurationName)"
xcopy  "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)" "$(ProjectDir)obj\$(ConfigurationName)" /E /R /Y

if $(ConfigurationName) == Release (
    dotnet publish "$(ProjectFileName)" --runtime win-$(PlatformName) --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
) else (
    dotnet publish "$(ProjectFileName)" --no-build -c $(ConfigurationName) -o pub --no-restore --no-dependencies
)

xcopy "$(ProjectDir)pub\my3rdPartyCompany.*.dll" "$(OutDir)" /Y /R

説明:dotnet publishはobj\Debugまたはを探していobj\Releaseます。ビルドはobj\x64\Releaseまたはを作成するため、ビルド中にはありませんobj\x86\Release。1行目と2行目は、この問題を軽減します。3行目ではdotnet.exe、特定の構成とターゲットランタイムを使用するように指示しています。それ以外の場合、これがデバッグモードのときは、実行時のものや警告は気にしません。そして最後の行では、dllを取得して、出力フォルダーにコピーします。仕事が終わりました。


プロジェクトにデバッグ構成がない場合(私の場合など)、「dotnet publish」コマンドには「-c Release」パラメーターが必要です。だから私は、ビルド後のイベントとして、このバッチを使用: dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
Xtro

0

上記の回答と組み合わせて:ビルド後のイベントのコマンドラインであるVisual Studioでこれをうまく機能させています。選択したdll(System * .dllおよびMicrosoft .dll)*をループし、特定のdllの削除をスキップします。System.Data.SqlClient.dllおよびSystem.Runtime.Loader.dll

for %%f in ($(OutDir)System*.dll $(OutDir)Microsoft*.dll) do if not %%f == $(OutDir)System.Data.SqlClient.dll if not %%f == $(OutDir)System.Runtime.Loader.dll del %%f
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.