Làm cách nào để nhận các dự án .NET Core sao chép các tham chiếu NuGet vào đầu ra bản dựng?


108

Tôi đang cố gắng viết một hệ thống plugin với .NET Core và một trong những yêu cầu của tôi là có thể phân phối DLL plugin cùng với các phụ thuộc của nó cho người dùng để cài đặt.

Tuy nhiên, tôi không thể tìm ra cách bao gồm các phần phụ thuộc NuGet của mình dưới dạng tạo tác bản dựng và đưa chúng xuất ra thư mục bản dựng mà không cần phải sử dụng dotnet publishnhư một bản hack. Có cách nào tôi có thể chỉ định điều này trong tệp .csproj (tệp dự án) không?


2
Tại sao sử dụng sẽ dotnet publishlà một hack? Bao gồm lệnh trong tệp csproj của bạn dưới dạng tập lệnh tạo bài đăng.
Austin Drenski

3
dotnet publishném toàn bộ khung công tác vào thư mục xuất bản, vì tôi đang viết một plugin nên phần lớn các tệp không cần thiết vì khung công tác đã được tải bởi chương trình bootstrapper. Tôi đang tìm kiếm thứ gì đó tương tự như cách các bản dựng hoạt động trên .NET Framework.
chyyran

Và bao gồm <CopyToOutputDirectory>Always</CopyToOutputDirectory>trong csproj của bạn trên mỗi hình nền bạn muốn di chuyển không làm được điều đó? Có lẽ kết hợp với một <link>nút?
Austin Drenski

7
<PackageReference/>không hỗ trợ <CopyToOutputDirectory>.
chyyran

1
Tuy nhiên, "toàn bộ khuôn khổ" đến từ NuGet .. và nếu bạn chọn sao chép tất cả các hợp ngữ NuGet vào đầu ra bản dựng, bạn sẽ nhận được tất cả chúng ..
Martin Ullrich

Câu trả lời:


177

Bạn có thể thêm cái này vào <PropertyGroup>bên trong tệp csproj của mình để thực thi sao chép các hội đồng NuGet vào đầu ra bản dựng:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

Tuy nhiên, lưu ý rằng đầu ra bản dựng ( bin/Release/netcoreapp*/*) không được cho là có thể di động và có thể phân phối, đầu ra của dotnet publishlà. Nhưng trong trường hợp của bạn, sao chép các hợp ngữ vào đầu ra bản dựng có lẽ rất hữu ích cho mục đích thử nghiệm. Nhưng lưu ý rằng bạn cũng có thể sử dụng DependencyContextapi để giải quyết các DLL và vị trí của chúng là một phần của biểu đồ phụ thuộc của ứng dụng thay vì liệt kê một thư mục cục bộ.


7
Nó gây ra copy tất cả dlls, không chỉ dlls NuGet
Mohammad Dayyan

2
Core 2 Tôi cũng nhận được tất cả các DLL của Microsoft. Không chắc tại sao nhưng trước đây tôi chỉ nhận NuGet nhưng sau đó nó ngừng hoạt động? gây phiền nhiễu
Piotr Kula

4
@MartinUllrich Bạn có thể giải thích thêm về DependencyContext? Làm cách nào tôi có thể sử dụng nó để tìm một DLL không có trong thư mục ứng dụng? Nó đang ở đâu?
ygoe

2
không làm việc cho tôi asp.net lõi không sao chép System.ValueTuple.dll
Ali Yousefi

1
@AliYousefie system.valuietuple cho các dự án net framework nên không còn đến từ NuGet trên các phiên bản .NET Framework gần đây và xây dựng công cụ
Martin Ullrich

10

Bạn có thể sử dụng PostBuildEvent để tự động triển khai mô-đun trên bản dựng.

Để có được các hợp ngữ NuGet trong thư mục xây dựng, hãy thêm vào csproj của mô-đun của bạn

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

Xác định tệp mô-đun bạn muốn ở đâu bằng Bao gồm / Loại trừ (sửa đổi đường dẫn nếu cần)

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

Đặt lại thư mục xây dựng của bạn về mặc định và thêm 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>

Tôi bao gồm app_offline để tái chế ứng dụng nếu nó đã chạy để tránh lỗi tệp đang sử dụng.


Trong dự án của tôi, tôi có một sự phụ thuộc vào thư viện "Microsoft.Extensions.Logging.Log4Net.AspNetCore" NuGet, và nó không phải là một phần của Netcore, vì vậy phương pháp này sẽ không làm việc
sad_robot

4

Thêm

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

không hoạt động, nhưng thêm cái này vào tệp Framework .csproj:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

đã làm.


Điều này hoạt động tốt cho tôi khi tôi đang tham khảo các thư viện .net Standard 2.0 từ bên trong dự án .Net Framework 4.7.2. Không có gì khác đã sửa nó.
Grungondola

3

Tôi đã "giải quyết" (tạo ra công việc xung quanh) điều này theo cách đơn giản hơn.

Trong bài xây dựng

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

pub là thư mục mà bạn muốn nội dung đã xuất bản của mình được sắp xếp

LƯU Ý: tùy thuộc vào phiên bản dotnet.exebạn sử dụng, lệnh--no-build có thể không khả dụng.

Ví dụ, không có sẵn trong v2.0.3; và có sẵn trong v2.1.402. Tôi biết rằng VS2017 Update4 có v2.0.3. Và Update8 có 2.1.x

Cập nhật:

Thiết lập ở trên sẽ hoạt động trong môi trường gỡ lỗi cơ bản nhưng để đưa nó vào môi trường máy chủ / sản xuất xây dựng thì cần nhiều hơn thế. Trong ví dụ cụ thể này mà tôi phải giải quyết, chúng tôi xây dựng Release|x64Release|x86riêng biệt. Vì vậy, tôi đã tính cả hai. Nhưng để hỗ trợ dotnet publishlệnh xây dựng bài đăng , trước tiên tôi đã thêm vào RuntimeIdentifiertệp dự án.

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

Tại sao tôi cần nó và tại sao bạn có thể bỏ đi mà không có nó? Tôi cần điều này vì chương trình xây dựng của tôi được đặt thành cảnh báo chặn MSB3270 và không xây dựng được nếu nó xuất hiện. Cảnh báo này cho biết, "này, một số tệp trong phần phụ thuộc của bạn có định dạng sai". Nhưng bạn có nhớ mục tiêu của bài tập này không? Chúng ta cần kéo các tệp DLL phụ thuộc gói. Và trong nhiều trường hợp, nó không quan trọng nếu cảnh báo này có ở đó bởi vì việc xây dựng bài đăng sau không quan tâm. Một lần nữa, đây là chương trình xây dựng của tôi quan tâm. Vì vậy, tôi chỉ thêmRuntimeIdentifier vào 2 cấu hình tôi sử dụng trong quá trình xây dựng sản xuất.

Toàn bài xây dựng

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

Giải thích: dotnet xuất bản đang tìm kiếm obj\Debughoặc obj\Release. Chúng tôi không có nó trong quá trình xây dựng vì quá trình xây dựng tạo ra obj\x64\Releasehoặc obj\x86\Release. Dòng 1 và 2 giảm thiểu vấn đề này. Trong dòng 3, tôi yêu dotnet.execầu sử dụng cấu hình cụ thể và thời gian chạy mục tiêu. Nếu không, khi đây là chế độ gỡ lỗi, tôi không quan tâm đến nội dung thời gian chạy và cảnh báo. Và ở dòng cuối cùng, tôi chỉ cần lấy dlls của mình và sao chép sau đó vào thư mục đầu ra. Công việc hoàn thành.


Tham số "-c Release" là bắt buộc đối với lệnh "dotnet Publishing" nếu dự án không có cấu hình gỡ lỗi (như trong trường hợp của tôi). Vì vậy, tôi đã sử dụng lô này làm sự kiện sau xây dựng: dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
Xtro

0

Kết hợp với câu trả lời ở trên: Tôi đã làm điều này hoạt động tuyệt vời trong dòng lệnh Sự kiện sau xây dựng: trong Visual Studio. Nó lặp qua lựa chọn các dlls (Hệ thống * .dll và Microsoft .dll) *, rồi bỏ qua việc xóa các dlls cụ thể. System.Data.SqlClient.dllSystem.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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.