ฉันจะรับโปรเจ็กต์. NET Core เพื่อคัดลอกการอ้างอิง NuGet ไปยังเอาต์พุตบิลด์ได้อย่างไร


114

ฉันกำลังพยายามเขียนระบบปลั๊กอินด้วย. NET Core และข้อกำหนดอย่างหนึ่งของฉันคือต้องสามารถแจกจ่ายปลั๊กอิน DLL พร้อมกับการอ้างอิงไปยังผู้ใช้เพื่อติดตั้ง

อย่างไรก็ตามฉันไม่สามารถหาวิธีรวมการอ้างอิง NuGet ของฉันเป็นสิ่งประดิษฐ์ในการสร้างและส่งออกไปยังโฟลเดอร์สร้างโดยไม่ต้องใช้dotnet publishเป็นการแฮ็ก มีวิธีใดบ้างที่ฉันสามารถระบุสิ่งนี้ในไฟล์. csproj (ไฟล์โครงการ)


2
ทำไมต้องใช้dotnet publishbe hack? รวมคำสั่งในไฟล์ csproj ของคุณเป็นสคริปต์สร้างโพสต์
Austin Drenski

3
dotnet publishโยนเฟรมเวิร์กทั้งหมดในโฟลเดอร์เผยแพร่เนื่องจากฉันกำลังเขียนปลั๊กอินไฟล์ส่วนใหญ่จึงไม่จำเป็นเนื่องจากเฟรมเวิร์กจะถูกโหลดโดยโปรแกรม bootstrapper อยู่แล้ว ฉันกำลังมองหาสิ่งที่คล้ายกับวิธีการสร้างงานบน. NET Framework
chyyran

และรวมถึง<CopyToOutputDirectory>Always</CopyToOutputDirectory>ใน csproj ของคุณในแต่ละ dll ที่คุณต้องการย้ายไม่ได้หลอกลวง อาจรวมกับ<link>โหนด?
Austin Drenski

7
<PackageReference/><CopyToOutputDirectory>ไม่สนับสนุน
chyyran

1
"เฟรมเวิร์กทั้งหมด" มาจาก NuGet แม้ว่า .. และหากคุณเลือกที่จะคัดลอกส่วนประกอบ NuGet ทั้งหมดไปยังเอาต์พุตบิลด์คุณจะได้รับทั้งหมด ..
Martin Ullrich

คำตอบ:


184

คุณสามารถเพิ่มสิ่งนี้ลง<PropertyGroup>ในไฟล์ csproj ของคุณเพื่อบังคับให้คัดลอกแอสเซมบลี NuGet ไปยังเอาต์พุตบิลด์:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

อย่างไรก็ตามโปรดทราบว่าเอาต์พุต build ( bin/Release/netcoreapp*/*) ไม่ควรเป็นแบบพกพาและกระจายได้ผลลัพธ์ของdotnet publishคือ. แต่ในกรณีของคุณการคัดลอกแอสเซมบลีไปยังเอาต์พุตบิลด์อาจมีประโยชน์มากสำหรับวัตถุประสงค์ในการทดสอบ แต่โปรดทราบว่าคุณยังสามารถใช้DependencyContextapi เพื่อแก้ไข DLL และตำแหน่งที่เป็นส่วนหนึ่งของกราฟการอ้างอิงของแอปพลิเคชันแทนการระบุไดเรกทอรีภายในเครื่อง


7
มันทำให้เกิดการคัดลอก dlls ทั้งหมดไม่ใช่แค่ Nuget dlls
Mohammad Dayyan

2
Core 2 ฉันได้รับ Microsoft DLL ทั้งหมดด้วย ไม่แน่ใจว่าทำไม แต่ก่อนฉันได้รับ NuGet แต่แล้วมันก็หยุดทำ? น่ารำคาญ
Piotr Kula

4
@MartinUllrich คุณสามารถอธิบายรายละเอียดเกี่ยวกับDependencyContext? ฉันจะใช้เพื่อค้นหา DLL ที่ไม่อยู่ในไดเรกทอรีแอปพลิเคชันได้อย่างไร อยู่ที่ไหนต่อไป?
ygoe

2
ไม่ทำงานสำหรับฉันแกน asp.net ไม่ได้คัดลอก System.ValueTuple.dll
Ali Yousefi

1
@AliYousefie system.valuietuple สำหรับโครงการ. net framework ไม่ควรมาจาก NuGet ในเวอร์ชัน. net framework ล่าสุดและการสร้างเครื่องมืออีกต่อไป
Martin Ullrich

10

คุณสามารถใช้ PostBuildEvent เพื่อปรับใช้โมดูลโดยอัตโนมัติในบิลด์

ในการรับแอสเซมบลี NuGet ในโฟลเดอร์ build ให้เพิ่มใน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>

รีเซ็ตโฟลเดอร์ build ของคุณเป็นค่าเริ่มต้นและเพิ่ม 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 เพื่อรีไซเคิลแอปหากแอปทำงานอยู่แล้วเพื่อหลีกเลี่ยงข้อผิดพลาดในการใช้งานไฟล์


ในโครงการของฉันฉันมีการพึ่งพาไลบรารี Nuget "Microsoft.Extensions.Logging.Log4Net.AspNetCore" และไม่ใช่ส่วนหนึ่งของ NetCore ดังนั้นวิธีนี้จะไม่ได้ผล
sad_robot

4

การเพิ่ม

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

ไม่ได้ผล แต่เพิ่มสิ่งนี้ลงในไฟล์ Framework .csproj:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>

เคยทำ.


สิ่งนี้ใช้ได้ดีสำหรับฉันเมื่อฉันอ้างถึงไลบรารี. net Standard 2.0 จากภายในโครงการ. Net Framework 4.7.2 ไม่มีอะไรอื่นที่แก้ไขได้
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|x64และRelease|x86แยกกัน ดังนั้นฉันจึงคิดเป็นทั้งสองอย่าง แต่เพื่อรองรับdotnet publishคำสั่งpost build ฉัน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 แบบพึ่งพาแพ็คเกจ และในหลาย ๆ กรณีมันไม่สำคัญว่าจะมีคำเตือนนี้หรือไม่เนื่องจากการสร้างโพสต์ต่อไปนี้ไม่สนใจ อีกครั้งนี่คือโปรแกรมสร้างของฉันที่ใส่ใจ ดังนั้นฉันจึงเพิ่มเพียงRuntimeIdentifier2 การกำหนดค่าที่ฉันใช้ระหว่างการสร้างการผลิต

สร้างโพสต์แบบเต็ม

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 เผยแพร่ที่กำลังมองหาหรือobj\Debug obj\Releaseเราไม่ได้มีมันในระหว่างการสร้างเพราะสร้างสร้างหรือobj\x64\Release obj\x86\Releaseบรรทัดที่ 1 และ 2 ช่วยบรรเทาปัญหานี้ ในบรรทัดที่ 3 ฉันบอกdotnet.exeให้ใช้การกำหนดค่าเฉพาะและรันไทม์เป้าหมาย มิฉะนั้นเมื่อเป็นโหมดดีบักฉันจะไม่สนใจเกี่ยวกับสิ่งที่รันไทม์และคำเตือน และในบรรทัดสุดท้ายฉันก็แค่ใช้ dll ของฉันแล้วคัดลอกไปที่โฟลเดอร์ผลลัพธ์ งานเสร็จแล้ว


พารามิเตอร์ "-c Release" จำเป็นสำหรับคำสั่ง "dotnet published" หากโปรเจ็กต์ไม่มีการกำหนดค่าการดีบัก (เช่นในกรณีของฉัน) ดังนั้นฉันจึงใช้ชุดนี้เป็นกิจกรรมหลังการสร้าง: dotnet publish "$(ProjectFileName)" -c Release --no-build -o bin\pub xcopy "$(ProjectDir)pub\PostSharp.dll" "$(OutDir)"
Xtro

0

ร่วมกับคำตอบข้างต้น: ฉันทำงานได้ดีในบรรทัดคำสั่งหลังสร้างเหตุการณ์:ใน Visual Studio มันวนซ้ำอยู่เหนือการเลือกของ dlls (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.