เพิ่มไฟล์เนทีฟจากแพ็คเกจ NuGet ไปยังไดเร็กทอรีเอาต์พุตของโปรเจ็กต์


126

ฉันกำลังพยายามสร้างแพ็คเกจ NuGet สำหรับแอสเซมบลี. Net ซึ่งจะปักหมุดเป็น win32 dll ดั้งเดิม ฉันต้องการแพ็คทั้งแอสเซมบลีและ dll ดั้งเดิมพร้อมกับแอสเซมบลีที่เพิ่มในการอ้างอิงโปรเจ็กต์ (ไม่มีปัญหาในส่วนนี้) และควรคัดลอก dll ดั้งเดิมลงในไดเร็กทอรีเอาต์พุตของโปรเจ็กต์หรือไดเร็กทอรีสัมพัทธ์อื่น ๆ

คำถามของฉันคือ:

  1. ฉันจะแพ็ค dll แบบเนทีฟโดยไม่ต้องวิชวลสตูดิโอพยายามเพิ่มลงในรายการอ้างอิงได้อย่างไร
  2. ฉันต้องเขียน install.ps1 เพื่อคัดลอก dll ดั้งเดิมหรือไม่ หากเป็นเช่นนั้นฉันจะเข้าถึงเนื้อหาแพ็กเกจเพื่อคัดลอกได้อย่างไร

1
มีการรองรับไลบรารีเฉพาะรันไทม์ / สถาปัตยกรรม แต่เอกสารประกอบคุณลักษณะขาดหายไปและดูเหมือนว่าจะเป็นเฉพาะ UWP docs.microsoft.com/en-us/nuget/create-packages/…
Wouter

คำตอบ:


132

การใช้Copyเป้าหมายในไฟล์เป้าหมายเพื่อคัดลอกไลบรารีที่ต้องการจะไม่คัดลอกไฟล์เหล่านั้นไปยังโปรเจ็กต์อื่นที่อ้างอิงโปรเจ็กต์ส่งผลให้ไฟล์DllNotFoundException. ซึ่งสามารถทำได้ด้วยไฟล์เป้าหมายที่ง่ายกว่ามากโดยใช้Noneองค์ประกอบเนื่องจาก MSBuild จะคัดลอกNoneไฟล์ทั้งหมดไปยังการอ้างอิงโครงการ

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

เพิ่มไฟล์เป้าหมายในbuildไดเร็กทอรีของแพ็กเกจ nuget พร้อมกับไลบรารีเนทีฟที่ต้องการ ไฟล์เป้าหมายจะรวมdllไฟล์ทั้งหมดในไดเร็กทอรีชายน์ทั้งหมดของbuildไดเร็กทอรี ดังนั้นในการเพิ่มx86และx64เวอร์ชันของไลบรารีเนทีฟที่ใช้โดยAny CPUแอสเซมบลีที่มีการจัดการคุณจะต้องมีโครงสร้างไดเร็กทอรีที่คล้ายกับสิ่งต่อไปนี้:

  • สร้าง
    • x86
      • NativeLib.dll
      • NativeLibDependency.dll
    • x64
      • NativeLib.dll
      • NativeLibDependency.dll
    • MyNugetPackageID.targets
  • lib
    • net40
      • ManagedAssembly.dll

ไดเร็กทอรีเดียวกันx86และx64จะถูกสร้างขึ้นในไดเร็กทอรีเอาต์พุตของโปรเจ็กต์เมื่อสร้าง ถ้าคุณไม่จำเป็นต้องไดเรกทอรีย่อยแล้ว**และ%(RecursiveDir)สามารถถอดออกและแทนรวมถึงไฟล์ที่จำเป็นในbuildไดเรกทอรีโดยตรง นอกจากนี้ยังสามารถเพิ่มไฟล์เนื้อหาที่จำเป็นอื่น ๆ ได้ในลักษณะเดียวกัน

ไฟล์ที่เพิ่มNoneในไฟล์เป้าหมายจะไม่แสดงในโปรเจ็กต์เมื่อเปิดใน Visual Studio หากคุณสงสัยว่าทำไมฉันไม่ใช้Contentโฟลเดอร์ใน nupkg เป็นเพราะไม่มีวิธีตั้งค่าCopyToOutputDirectoryองค์ประกอบโดยไม่ใช้สคริปต์ powershell (ซึ่งจะทำงานภายใน Visual Studio เท่านั้นไม่ใช่จากพรอมต์คำสั่งบนเซิร์ฟเวอร์ที่สร้างหรือใน IDE อื่น ๆ และไม่ได้รับการสนับสนุนในโปรเจ็กต์ project.json / xproj DNX ) และฉันชอบใช้ a Linkกับไฟล์มากกว่าที่จะมีสำเนาของไฟล์เพิ่มเติมภายในโปรเจ็กต์

อัปเดต: แม้ว่าสิ่งนี้ควรใช้งานได้Contentแทนที่จะNoneดูเหมือนว่ามีข้อผิดพลาดใน msbuild ดังนั้นไฟล์จะไม่ถูกคัดลอกไปยังการอ้างอิงโปรเจ็กต์มากกว่าหนึ่งขั้นตอนที่ลบออก (เช่น proj1 -> proj2 -> proj3, proj3 จะไม่ได้รับไฟล์ จากแพ็คเกจ NuGet ของ proj1 แต่ proj2 จะ)


4
คุณชายคุณเป็นอัจฉริยะ! ใช้งานได้เหมือนมีเสน่ห์ ขอบคุณ
MoonStom

สงสัยว่าทำไม'$(MSBuildThisFileDirectory)' != '' And HasTrailingSlash('$(MSBuildThisFileDirectory)')ต้องมีเงื่อนไข? ฉันคิดว่าMSBuildThisFileDirectoryตั้งค่าไว้เสมอ เมื่อนั้นจะไม่เป็นเช่นนั้น?
กม.

@kkm ด้วยความสัตย์จริง. ฉันไม่คิดว่ามันจำเป็น จำไม่ได้ด้วยซ้ำว่าได้มาจากไหน
kjbartel

@kkm เดิมทีฉันแก้ไขแพ็คเกจ System.Data.SQLite nuget และดูเหมือนว่าฉันจะทิ้งมันไว้ข้างหลังเมื่อฉันลบอึอื่น ๆ ทั้งหมดที่รวมอยู่ด้วย ไฟล์เป้าหมายเดิม
kjbartel

2
@SuperJMN มีสัญลักษณ์แทนอยู่ที่นั่น คุณไม่สังเกตเห็น**\*.dll? นั่นคือการคัดลอก.dllไฟล์ทั้งหมดในไดเรกทอรีทั้งหมด คุณสามารถ**\*.*คัดลอกโครงสร้างไดเรกทอรีทั้งหมดได้อย่างง่ายดาย
kjbartel

30

เมื่อเร็ว ๆ นี้ฉันมีปัญหาเดียวกันเมื่อฉันพยายามสร้างแพ็คเกจ EmguCV NuGet ซึ่งรวมถึงแอสเซมบลีที่มีการจัดการและไลเรรีที่ใช้ร่วมกันที่ไม่มีการจัดการ (ซึ่งต้องวางไว้ในx86ไดเร็กทอรีย่อยด้วย) ซึ่งจะต้องถูกคัดลอกโดยอัตโนมัติไปยังไดเร็กทอรีเอาต์พุตของบิลด์หลังจากแต่ละบิลด์.

นี่คือวิธีแก้ปัญหาที่ฉันคิดขึ้นซึ่งอาศัยเฉพาะ NuGet และ MSBuild:

  1. วางแอสเซมบลีที่มีการจัดการใน/libไดเร็กทอรีของแพ็กเกจ (ส่วนที่ชัดเจน) และไลบรารีแบบแบ่งใช้ที่ไม่มีการจัดการและไฟล์ที่เกี่ยวข้อง (เช่นแพ็กเกจ. pdb) ใน/buildไดเร็กทอรีย่อย (ตามที่อธิบายไว้ในเอกสาร NuGet )

  2. เปลี่ยนชื่อส่วน*.dllท้ายไฟล์ที่ไม่มีการจัดการทั้งหมดเป็นชื่ออื่นเช่น*.dl_เพื่อป้องกันไม่ให้ NuGet คร่ำครวญเกี่ยวกับแอสเซมบลีที่ถูกกล่าวหาว่าวางผิดตำแหน่ง ( "ปัญหา: ประกอบนอกโฟลเดอร์ lib" )

  3. เพิ่ม<PackageName>.targetsไฟล์ที่กำหนดเองใน/buildไดเร็กทอรีย่อยด้วยเนื้อหาต่อไปนี้ (ดูคำอธิบายด้านล่าง):

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <ItemGroup>
        <AvailableItemName Include="NativeBinary" />
      </ItemGroup>
      <ItemGroup>
        <NativeBinary Include="$(MSBuildThisFileDirectory)x86\*">
          <TargetPath>x86</TargetPath>
        </NativeBinary>
      </ItemGroup>
      <PropertyGroup>
        <PrepareForRunDependsOn>
          $(PrepareForRunDependsOn);
          CopyNativeBinaries
        </PrepareForRunDependsOn>
      </PropertyGroup>
      <Target Name="CopyNativeBinaries" DependsOnTargets="CopyFilesToOutputDirectory">
        <Copy SourceFiles="@(NativeBinary)"
              DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).dll')"
              Condition="'%(Extension)'=='.dl_'">
          <Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
        </Copy>
        <Copy SourceFiles="@(NativeBinary)"
              DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).%(Extension)')"
              Condition="'%(Extension)'!='.dl_'">
          <Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
        </Copy>
      </Target>
    </Project>
    

.targetsไฟล์ด้านบนจะถูกแทรกในการติดตั้งแพ็คเกจ NuGet ในไฟล์โปรเจ็กต์เป้าหมายและรับผิดชอบในการคัดลอกไลบรารีเนทีฟไปยังไดเร็กทอรีเอาต์พุต

  • <AvailableItemName Include="NativeBinary" /> เพิ่มรายการใหม่ "Build Action" สำหรับโปรเจ็กต์ (ซึ่งจะพร้อมใช้งานในเมนูแบบเลื่อนลง "Build Action" ภายใน Visual Studio)

  • <NativeBinary Include="...เพิ่มไลบรารีเนทีฟที่วางไว้ใน/build/x86โปรเจ็กต์ปัจจุบันและทำให้เข้าถึงได้โดยกำหนดเป้าหมายเองซึ่งคัดลอกไฟล์เหล่านั้นไปยังไดเร็กทอรีเอาต์พุต

  • <TargetPath>x86</TargetPath>เพิ่มข้อมูลเมตาที่กำหนดเองให้กับไฟล์และบอกให้เป้าหมายที่กำหนดเองคัดลอกไฟล์เนทีฟไปยังx86ไดเร็กทอรีย่อยของไดเร็กทอรีเอาต์พุตจริง

  • <PrepareForRunDependsOn ...บล็อกเพิ่มเป้าหมายที่กำหนดเองในรายการของเป้าหมายสร้างขึ้นอยู่กับการให้ดูที่Microsoft.Common.targetsไฟล์สำหรับรายละเอียด

  • เป้าหมายที่กำหนดเองCopyNativeBinariesประกอบด้วยงานคัดลอกสองงาน คนแรกเป็นผู้รับผิดชอบสำหรับการคัดลอกใด ๆไฟล์ไปยังไดเรกทอรีออกขณะที่การเปลี่ยนกลับมาขยายของพวกเขาเพื่อไปที่เดิม*.dl_ *.dllอันที่สองเพียงแค่คัดลอกส่วนที่เหลือ (เช่น*.pdbไฟล์ใด ๆ) ไปยังตำแหน่งเดียวกัน สิ่งนี้สามารถแทนที่ได้ด้วยงานสำเนาเดียวและสคริปต์install.ps1ซึ่งต้องเปลี่ยนชื่อ*.dl_ไฟล์ทั้งหมดเป็น*.dllระหว่างการติดตั้งแพ็คเกจ

อย่างไรก็ตามโซลูชันนี้ยังคงไม่คัดลอกไบนารีดั้งเดิมไปยังไดเร็กทอรีเอาต์พุตของโปรเจ็กต์อื่นที่อ้างถึงอันที่รวมแพ็คเกจ NuGet ไว้ในตอนแรก คุณยังต้องอ้างอิงแพ็คเกจ NuGet ในโปรเจ็กต์ "ขั้นสุดท้าย" ของคุณด้วย


4
" อย่างไรก็ตามโซลูชันนี้ยังคงไม่คัดลอกไบนารีดั้งเดิมไปยังไดเร็กทอรีเอาต์พุตของโปรเจ็กต์อื่นที่อ้างถึงแพ็กเกจ NuGet ในขั้นต้นคุณยังคงต้องอ้างอิงแพ็กเกจ NuGet ในโปรเจ็กต์" ขั้นสุดท้าย "ของคุณด้วยเช่นกัน " นี่คือ แสดงจุกให้ฉัน โดยทั่วไปหมายความว่าคุณต้องเพิ่มแพ็กเกจนักเก็ตในหลายโครงการ (เช่นการทดสอบหน่วย) มิฉะนั้นคุณจะDllNotFoundExceptionถูกโยนทิ้ง
kjbartel

2
ค่อนข้างรุนแรงในการเปลี่ยนชื่อไฟล์และอื่น ๆ เพียงเพราะคำเตือน

คุณสามารถลบคำเตือนโดยเพิ่ม<NoWarn>NU5100</NoWarn>ลงในไฟล์โครงการของคุณ
Florian Koch

29

นี่คืออีกทางเลือกหนึ่งที่ใช้.targetsเพื่อฉีด DLL ดั้งเดิมในโปรเจ็กต์ด้วยคุณสมบัติต่อไปนี้

  • Build action = None
  • Copy to Output Directory = Copy if newer

ประโยชน์หลักของเทคนิคนี้คือการคัดลอก DLL ดั้งเดิมไปไว้ในbin/โฟลเดอร์ของโปรเจ็กต์ที่ขึ้นอยู่กับสกรรมกริยา

ดูเค้าโครงของ.nuspecไฟล์:

การจับภาพหน้าจอของ NuGet Package Explorer

นี่คือ.targetsไฟล์:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <None Include="$(MSBuildThisFileDirectory)\..\MyNativeLib.dll">
            <Link>MyNativeLib.dll</Link>
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>
</Project>

สิ่งนี้จะแทรกMyNativeLib.dllราวกับว่าเป็นส่วนหนึ่งของโปรเจ็กต์ดั้งเดิม (แต่อยากรู้อยากเห็นไฟล์ไม่สามารถมองเห็นได้ใน Visual Studio)

สังเกต<Link>องค์ประกอบที่ตั้งชื่อไฟล์ปลายทางในbin/โฟลเดอร์


ใช้งานได้กับไฟล์. bat และ. ps1 บางไฟล์ที่ฉันต้องการรวมเป็นส่วนหนึ่งของบริการ Azure ของฉัน - ขอบคุณ :)
Zhaph - Ben Duguid

“ (แต่อยากรู้อยากเห็นไฟล์ไม่ปรากฏใน Visual Studio)” - ไฟล์โปรเจ็กต์ถูกแยกวิเคราะห์โดย VS เอง AFAIK ดังนั้นรายการที่เพิ่มในไฟล์. Target ภายนอก (หรือไฟล์ที่สร้างแบบไดนามิกในการดำเนินการเป้าหมาย) จะไม่แสดง
กม.

สิ่งนี้แตกต่างจากคำตอบก่อนหน้าอื่น ๆ นอกเหนือจากการเปลี่ยนจากContentเป็นNoneอย่างไร
kjbartel

3
ว้าวคุณเร็ว อย่างไรก็ตามหากคุณเลือกที่จะทำอย่างนั้นอย่างน้อยคุณก็สามารถถามว่า 'สิ่งนี้แตกต่างจากคำตอบของฉันอย่างไร' imo นั้นจะยุติธรรมกว่าการแก้ไขคำถามเดิมตอบคำถามด้วยตัวเองจากนั้นส่งเสริมคำตอบของคุณในความคิดเห็นของคนอื่น ไม่ต้องพูดถึงว่าโดยส่วนตัวแล้วฉันชอบคำตอบนี้ดีกว่าของคุณ - มันกระชับตรงประเด็นและอ่านง่ายขึ้น
มักซิมซัตซิเกา

3
@MaksimSatsikau คุณอาจต้องการดูประวัติ ฉันแก้ไขคำถามเพื่อให้ชัดเจนขึ้นจากนั้นจึงตอบคำถาม คำตอบนี้เกิดขึ้นสองสามสัปดาห์ต่อมาและเป็นสำเนาที่มีประสิทธิภาพ ขออภัยหากพบว่าหยาบคาย
kjbartel

20

ถ้าใครเจอแบบนี้

.targetsชื่อไฟล์ต้องเท่ากับ Id แพคเกจ NuGet

อย่างอื่นจะไม่ได้ผล

เครดิตไปที่: https://sushihangover.github.io/nuget-and-msbuild-targets/

ฉันควรอ่านอย่างละเอียดมากขึ้นตามที่ระบุไว้ที่นี่ อายุ ...

เพิ่มแบบกำหนดเอง <PackageName>.targets


3
คุณช่วยฉันทั้งวัน!
zheng yu

1
คุณแก้ไขปัญหาที่ยาวนานหนึ่งสัปดาห์ด้วยอย่างอื่น ขอบคุณคุณและเพจ github
Glenn Watson

13

มันช้าไปหน่อย แต่ฉันได้สร้างแพ็คเกจที่ยอดเยี่ยมสำหรับสิ่งนั้น

แนวคิดคือการมีโฟลเดอร์พิเศษเพิ่มเติมในแพ็คเกจ nuget ของคุณ ฉันแน่ใจว่าคุณรู้จัก Lib และ Content อยู่แล้ว แพ็คเกจ nuget ที่ฉันสร้างขึ้นจะมองหาโฟลเดอร์ชื่อ Output และจะคัดลอกทุกอย่างที่อยู่ในนั้นไปยังโฟลเดอร์ผลลัพธ์ของโครงการ

สิ่งเดียวที่คุณต้องทำคือเพิ่ม nuget dependency ลงในแพ็คเกจhttp://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/

ฉันเขียนบล็อกโพสต์เกี่ยวกับเรื่องนี้: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=6&mobile=0


ที่น่ากลัว! อย่างไรก็ตามสิ่งนี้ใช้ได้เฉพาะในโครงการปัจจุบัน หากโปรเจ็กต์เป็น "ไลบรารีคลาส" และคุณต้องการเพิ่มการพึ่งพาให้กับ "แอปพลิเคชันเว็บ" เช่น DLLs จะไม่ถูกสร้างในเว็บแอปพลิเคชัน! "การแก้ไขด่วน" ของฉันคือสร้าง NuGet สำหรับไลบรารีของคุณและใช้กับไลบรารีคลาสและสร้าง Nuget อื่นสำหรับการอ้างอิง (dlls ในกรณีนี้) และนำไปใช้กับ WebApplication ทางออกที่ดีที่สุดสำหรับสิ่งนี้หรือไม่?
Wagner Leonardi

ดูเหมือนว่าคุณจะสร้างโปรเจ็กต์นี้สำหรับ. NET 4.0 (Windows) เท่านั้น คุณวางแผนที่จะอัปเดตเพื่อรองรับไลบรารีคลาสพกพาด้วยหรือไม่?
Ani

1

มีโซลูชัน C # ที่บริสุทธิ์ซึ่งฉันพบว่าค่อนข้างใช้งานง่ายและฉันไม่ต้องกังวลกับข้อ จำกัด ของ NuGet ทำตามขั้นตอนเหล่านี้:

Embedded Resourceรวมถึงห้องสมุดพื้นเมืองในโครงการของคุณและตั้งค่าคุณสมบัติการสร้างการดำเนินการของ

วางรหัสต่อไปนี้ลงในคลาสที่คุณคลิกไลบรารีนี้

private static void UnpackNativeLibrary(string libraryName)
{
    var assembly = Assembly.GetExecutingAssembly();
    string resourceName = $"{assembly.GetName().Name}.{libraryName}.dll";

    using (var stream = assembly.GetManifestResourceStream(resourceName))
    using (var memoryStream = new MemoryStream(stream.CanSeek ? (int)stream.Length : 0))
    {
        stream.CopyTo(memoryStream);
        File.WriteAllBytes($"{libraryName}.dll", memoryStream.ToArray());
    }
}

เรียกเมธอดนี้จากตัวสร้างแบบคงที่ดังนี้UnpackNativeLibrary("win32");และมันจะคลายไลบรารีลงในดิสก์ก่อนที่คุณจะต้องการ แน่นอนคุณต้องแน่ใจว่าคุณมีสิทธิ์ในการเขียนลงในส่วนนั้นของดิสก์


1

นี่เป็นคำถามเก่า แต่ตอนนี้ฉันมีปัญหาเดียวกันและฉันพบการตอบสนองที่ยุ่งยากเล็กน้อย แต่เรียบง่ายและมีประสิทธิภาพมาก: สร้างในโฟลเดอร์เนื้อหามาตรฐาน Nuget ตามโครงสร้างต่อไปนี้โดยมีโฟลเดอร์ย่อยหนึ่งโฟลเดอร์สำหรับแต่ละการกำหนดค่า:

/Content
 /bin
   /Debug
      native libraries
   /Release
      native libraries

เมื่อคุณแพ็คไฟล์ nuspec คุณจะได้รับข้อความต่อไปนี้สำหรับแต่ละไลบรารีเนทีฟในโฟลเดอร์ Debug and Release:

ปัญหา: ประกอบนอกโฟลเดอร์ lib คำอธิบาย: แอสเซมบลี 'Content \ Bin \ Debug \ ??????. dll' ไม่ได้อยู่ในโฟลเดอร์ 'lib' ดังนั้นจะไม่ถูกเพิ่มเป็นข้อมูลอ้างอิงเมื่อติดตั้งแพ็คเกจลงในโปรเจ็กต์ วิธีแก้ไข: ย้ายไปไว้ในโฟลเดอร์ 'lib' หากควรอ้างอิง

เราไม่ต้องการ "โซลูชัน" ดังกล่าวเพราะนี่เป็นเพียงเป้าหมายของเรา: ไลบรารีเนทีฟจะไม่ถูกเพิ่มเข้าไปในการอ้างอิง NET Assemblies

ข้อดีคือ:

  1. วิธีแก้ปัญหาง่ายๆโดยไม่มีสคริปต์ที่ยุ่งยากพร้อมเอฟเฟกต์แปลก ๆ ที่ยากต่อการรีเซ็ตเมื่อถอนการติดตั้งแพ็คเกจ
  2. Nuget จัดการไลบรารีดั้งเดิมเป็นเนื้อหาอื่น ๆ เมื่อติดตั้งและถอนการติดตั้ง

ข้อเสียคือ:

  1. คุณต้องมีโฟลเดอร์สำหรับแต่ละการกำหนดค่า (แต่โดยปกติจะมีเพียงสองโฟลเดอร์เท่านั้น: Debug และ Release และหากคุณมีเนื้อหาอื่น ๆ ที่ต้องติดตั้งในโฟลเดอร์การกำหนดค่าแต่ละโฟลเดอร์นี่เป็นวิธีที่จะไป)
  2. ไลบรารีเนทีฟต้องซ้ำกันในแต่ละโฟลเดอร์คอนฟิกูเรชัน (แต่ถ้าคุณมีไลบรารีเนทีฟเวอร์ชันต่างกันสำหรับแต่ละคอนฟิกูเรชันนี่เป็นวิธีที่จะไป)
  3. คำเตือนสำหรับ dll เนทีฟแต่ละตัวในแต่ละโฟลเดอร์ (แต่อย่างที่ฉันพูดคำเตือนจะออกให้กับผู้สร้างแพ็คเกจในเวลาแพ็คไม่ใช่ให้กับผู้ใช้แพ็คเกจในเวลาติดตั้ง VS)

0

ฉันไม่สามารถแก้ปัญหาที่แน่นอนของคุณได้ แต่ฉันสามารถให้คำแนะนำกับคุณได้

ข้อกำหนดหลักของคุณคือ: "และห้ามลงทะเบียนข้อมูลอ้างอิงอัตโนมัติ" .....

ดังนั้นคุณจะต้องทำความคุ้นเคยกับ "รายการโซลูชัน"

ดูข้อมูลอ้างอิงที่นี่:

การเพิ่มรายการระดับโซลูชันในแพ็คเกจ NuGet

คุณจะต้องเขียน powershell voodoo เพื่อรับสำเนาของ dll พื้นเมืองของคุณในบ้าน (อีกครั้งเพราะคุณไม่ต้องการให้วูดูที่เพิ่มการอ้างอิงอัตโนมัติเริ่มทำงาน)

นี่คือไฟล์ ps1 ที่ฉันเขียน ..... เพื่อใส่ไฟล์ในโฟลเดอร์อ้างอิงของบุคคลที่สาม

มีเพียงพอสำหรับคุณที่จะหาวิธีคัดลอก dll พื้นเมืองของคุณไปยัง "บ้าน" ... โดยไม่ต้องเริ่มต้นใหม่

อีกครั้งไม่ใช่การโจมตีโดยตรง แต่ดีกว่าไม่มีอะไรเลย

param($installPath, $toolsPath, $package, $project)
if ($project -eq $null) {
$project = Get-Project
}

Write-Host "Start Init.ps1" 

<#
The unique identifier for the package. This is the package name that is shown when packages are listed using the Package Manager Console. These are also used when installing a package using the Install-Package command within the Package Manager Console. Package IDs may not contain any spaces or characters that are invalid in an URL.
#>
$separator = " "
$packageNameNoVersion = $package -split $separator | select -First 1

Write-Host "installPath:" "${installPath}"
Write-Host "toolsPath:" "${toolsPath}"
Write-Host "package:" "${package}"
<# Write-Host "project:" "${project}" #>
Write-Host "packageNameNoVersion:" "${packageNameNoVersion}"
Write-Host " "

<# Recursively look for a .sln file starting with the installPath #>
$parentFolder = (get-item $installPath)
do {
        $parentFolderFullName = $parentFolder.FullName

        $latest = Get-ChildItem -Path $parentFolderFullName -File -Filter *.sln | Select-Object -First 1
        if ($latest -ne $null) {
            $latestName = $latest.name
            Write-Host "${latestName}"
        }

        if ($latest -eq $null) {
            $parentFolder = $parentFolder.parent    
        }
}
while ($parentFolder -ne $null -and $latest -eq $null)
<# End recursive search for .sln file #>


if ( $parentFolder -ne $null -and $latest -ne $null )
{
    <# Create a base directory to store Solution-Level items #>
    $thirdPartyReferencesDirectory = $parentFolder.FullName + "\ThirdPartyReferences"

    if ((Test-Path -path $thirdPartyReferencesDirectory))
    {
        Write-Host "--This path already exists: $thirdPartyReferencesDirectory-------------------"
    }
    else
    {
        Write-Host "--Creating: $thirdPartyReferencesDirectory-------------------"
        New-Item -ItemType directory -Path $thirdPartyReferencesDirectory
    }

    <# Create a sub directory for only this package.  This allows a clean remove and recopy. #>
    $thirdPartyReferencesPackageDirectory = $thirdPartyReferencesDirectory + "\${packageNameNoVersion}"

    if ((Test-Path -path $thirdPartyReferencesPackageDirectory))
    {
        Write-Host "--Removing: $thirdPartyReferencesPackageDirectory-------------------"
        Remove-Item $thirdPartyReferencesPackageDirectory -Force -Recurse
    }

    if ((Test-Path -path $thirdPartyReferencesPackageDirectory))
    {
    }
    else
    {
        Write-Host "--Creating: $thirdPartyReferencesPackageDirectory-------------------"
        New-Item -ItemType directory -Path $thirdPartyReferencesPackageDirectory
    }

    Write-Host "--Copying all files for package : $packageNameNoVersion-------------------"
    Copy-Item $installPath\*.* $thirdPartyReferencesPackageDirectory -recurse
}
else
{
        Write-Host "A current or parent folder with a .sln file could not be located."
}


Write-Host "End Init.ps1" 

-2

ใส่ไว้คือโฟลเดอร์เนื้อหา

คำสั่งnuget pack [projfile].csprojจะดำเนินการให้คุณโดยอัตโนมัติหากคุณจะทำเครื่องหมายไฟล์ว่าเป็นเนื้อหา

จากนั้นแก้ไขไฟล์โครงการตามที่กล่าวไว้ที่นี่โดยเพิ่ม ItemGroup & NativeLibs & None element

<ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
</ItemGroup>

ทำงานให้ฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.