Bagaimana cara mendapatkan proyek .NET Core untuk menyalin referensi NuGet ke output build?

111

Saya mencoba untuk menulis sistem plugin dengan .NET Core, dan salah satu persyaratan saya adalah untuk dapat mendistribusikan plugin DLL bersama dengan dependensinya kepada pengguna untuk diinstal.

Namun, saya tidak tahu cara menyertakan dependensi NuGet saya sebagai artefak build dan mengeluarkannya ke folder build, tanpa harus digunakan dotnet publishsebagai hack. Apakah ada cara agar saya dapat menentukan ini di file .csproj (file proyek)?

chyyran
sumber
2
Mengapa menggunakan dotnet publishmenjadi hack? Sertakan perintah dalam file csproj Anda sebagai skrip post build.
Austin Drenski
3
dotnet publishmelempar seluruh kerangka kerja di folder terbitkan, karena saya sedang menulis plugin, sebagian besar file tidak diperlukan karena kerangka kerja sudah dimuat oleh program bootstrapper. Saya mencari sesuatu yang mirip dengan cara kerja build di .NET Framework.
chyyran
Dan termasuk <CopyToOutputDirectory>Always</CopyToOutputDirectory>dalam csproj Anda pada setiap dll yang ingin Anda pindahkan tidak berhasil? Mungkin digabungkan dengan <link>node?
Austin Drenski
7
<PackageReference/>tidak mendukung <CopyToOutputDirectory>.
chyyran
1
"Seluruh kerangka kerja" berasal dari NuGet .. dan jika Anda memilih untuk menyalin semua rakitan NuGet ke keluaran build, Anda akan mendapatkan semuanya ..
Martin Ullrich

Jawaban:

179

Anda dapat menambahkan ini ke <PropertyGroup>dalam file csproj Anda untuk memaksa penyalinan rakitan NuGet ke output build:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

Namun, perhatikan bahwa keluaran build ( bin/Release/netcoreapp*/*) tidak seharusnya portabel dan dapat didistribusikan, keluarannya dotnet publishadalah. Namun dalam kasus Anda, menyalin rakitan ke keluaran build mungkin sangat berguna untuk tujuan pengujian. Namun perhatikan bahwa Anda juga dapat menggunakan DependencyContextapi untuk menyelesaikan DLL dan lokasinya yang merupakan bagian dari grafik ketergantungan aplikasi alih-alih menghitung direktori lokal.

Martin Ullrich
sumber
7
Ini menyebabkan salin semua dll, bukan hanya Nuget dll
Mohammad Dayyan
2
Core 2 Saya mendapatkan semua Microsoft DLL juga. Tidak yakin mengapa tetapi sebelumnya saya hanya mendapatkan NuGet tetapi kemudian berhenti melakukannya? mengganggu
Piotr Kula
4
@MartinUllrich Dapatkah Anda menjelaskan lebih lanjut DependencyContext? Bagaimana saya dapat menggunakannya untuk menemukan DLL yang tidak ada di direktori aplikasi? Dimana sih itu?
ygoe
2
tidak bekerja untuk saya inti asp.net tidak menyalin System.ValueTuple.dll
Ali Yousefi
1
@AliYousefie system.valuietuple untuk proyek .net framework seharusnya tidak lagi berasal dari NuGet pada versi framework .net terbaru dan tooling build
Martin Ullrich
10

Anda dapat menggunakan PostBuildEvent untuk mengotomatiskan penerapan modul pada build.

Untuk mendapatkan assemblies NuGet di folder build tambahkan csproj modul Anda

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

Tentukan file modul apa yang Anda inginkan di mana menggunakan Include / Exclude (ubah jalur seperlunya)

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

Setel ulang folder build Anda ke default dan tambahkan 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>

Saya menyertakan app_offline untuk mendaur ulang aplikasi jika sudah berjalan untuk menghindari kesalahan penggunaan file.

Xeevis
sumber
Dalam proyek saya, saya memiliki ketergantungan pada pustaka Nuget "Microsoft.Extensions.Logging.Log4Net.AspNetCore", dan ini bukan bagian dari NetCore, jadi pendekatan ini tidak akan berfungsi
sad_robot
4

Menambahkan

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

tidak berfungsi, tetapi menambahkan ini ke file Framework .csproj:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

melakukan.

Mike Brunner
sumber
Ini bekerja dengan baik untuk saya ketika saya mereferensikan pustaka .net Standard 2.0 dari dalam proyek .Net Framework 4.7.2. Tidak ada yang bisa memperbaikinya.
Grungondola
3

Saya "memecahkan" (membuat solusi) ini dengan cara yang lebih sederhana.

Dalam posting membangun

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

pub adalah folder tempat Anda ingin item yang telah dipublikasikan digunakan untuk pementasan

CATATAN: tergantung pada versi apa yang dotnet.exeAnda gunakan, perintah --no-buildmungkin tidak tersedia.

Misalnya, tidak tersedia di v2.0.3; dan tersedia di v2.1.402. Saya tahu bahwa VS2017 Update4 memiliki v2.0.3. Dan Update8 memiliki 2.1.x

Memperbarui:

Penyiapan di atas akan bekerja di lingkungan debug dasar tetapi untuk memasukkannya ke lingkungan server / produksi build lebih banyak yang dibutuhkan. Dalam contoh khusus yang harus saya pecahkan ini, kami membangun Release|x64dan Release|x86secara terpisah. Jadi saya memperhitungkan keduanya. Tapi untuk mendukung perintah post build dotnet publish, saya tambahkan dulu RuntimeIdentifierke file project.

<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>

Mengapa saya membutuhkannya dan mengapa Anda bisa pergi tanpanya? Saya memerlukan ini karena program build saya disetel untuk mencegat peringatan MSB3270 , dan gagal membangun jika muncul. Peringatan ini mengatakan, "hei, beberapa file dalam dependensi Anda memiliki format yang salah". Tetapi apakah Anda ingat tujuan dari latihan ini? Kita perlu menarik DLL ketergantungan paket. Dan dalam banyak kasus tidak masalah jika peringatan ini ada karena mengikuti posting membangun tidak peduli. Sekali lagi, ini adalah program build saya yang peduli. Jadi, saya hanya menambahkan RuntimeIdentifierke 2 konfigurasi yang saya gunakan selama pembuatan produksi.

Full Post build

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

Penjelasan: dotnet publish sedang mencari obj\Debugatau obj\Release. Kami tidak memilikinya selama pembuatan karena build membuat obj\x64\Releaseatau obj\x86\Release. Baris 1 dan 2 mengurangi masalah ini. Sejalan 3 saya memberitahu dotnet.exeuntuk menggunakan konfigurasi tertentu dan target runtime. Jika tidak, saat ini adalah mode debug, saya tidak peduli tentang hal-hal runtime dan peringatan. Dan di baris terakhir saya cukup mengambil dll saya dan menyalinnya ke folder output. Pekerjaan selesai.

TS
sumber
Parameter "-c Release" diperlukan untuk perintah "dotnet publish" jika proyek tidak memiliki konfigurasi debug (seperti dalam kasus saya). Jadi saya menggunakan batch ini sebagai acara pasca-pembuatan: dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
Xtro
0

Sehubungan dengan jawaban di atas: Saya mendapatkan ini berfungsi dengan baik di baris perintah acara Post-build: di Visual Studio. Ini mengulang pilihan dll (System * .dll dan Microsoft .dll) *, dan kemudian melewatkan penghapusan dll tertentu. System.Data.SqlClient.dll dan 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
seabass
sumber