Visual Studio: วิธี“ คัดลอกไปยังไดเรกทอรีผลลัพธ์” โดยไม่ต้องคัดลอกโครงสร้างโฟลเดอร์?


111

ฉันมีไฟล์ dll สองสามไฟล์ในโฟลเดอร์ \ lib ของโฟลเดอร์โครงการของฉัน ในหน้าคุณสมบัติของ dll ฉันได้เลือก "Build Action" เป็น "Content" และ "Copy to Output Directory" เป็น "Copy always"

หลังจากสร้างแล้วฉันได้รับการคัดลอก dll แต่อยู่ภายใน \ bin \ Release \ lib และไม่ได้อยู่ใน \ bin \ Release

มีวิธีคัดลอกไฟล์ dll ไปยัง \ bin \ Release (และไม่ไปที่ \ bin \ Release \ lib) โดยไม่ต้องเขียนสคริปต์หลังการสร้างหรือหันไปใช้ nant ฯลฯ หรือไม่?

คำตอบ:


256

แทนที่จะ<Content>ใช้<ContentWithTargetPath>และระบุเส้นทางเป้าหมายเช่นนี้:

<ItemGroup>
  <ContentWithTargetPath Include="lib\some_file.dat">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <TargetPath>some_file.dat</TargetPath>
  </ContentWithTargetPath>
</ItemGroup>

โปรดทราบว่ารายการนี้อาจไม่สามารถมองเห็นได้จาก Visual Studio (2012, 2015, 2017) แต่เมื่อเพิ่มลงใน csproj ด้วยตนเองแล้วรายการนี้จะปรากฏใน Visual Studio เส้นทางเป้าหมายจะไม่สามารถแก้ไขได้ผ่าน UI


2
ฉันไม่เห็น ContentWithTargetPath เป็นตัวเลือก Build Action ใน VS 2015 มีวิธีเพิ่มหรือไม่
คิม

1
เมื่อฉันเพิ่มรายการด้วยตนเองในไฟล์. csproj จะปรากฏเป็นตัวเลือกใน IDE อย่างไรก็ตามฉันยังไม่สามารถแก้ไข Target Path จาก IDE ได้
คิม

9
สิ่งเดียวที่ฉันกังวลคือสิ่งนี้จะไม่รองรับ MSBuild / .NET / Visual Studio / อะไรก็ตามในอนาคตเนื่องจาก UI VS2015 ไม่แสดงตัวเลือกนี้หรือคุณสมบัติ TargetPath
MarioDS

1
สิ่งนี้ใช้ได้กับฉัน ไม่มีคำตอบอื่นใดที่เหมาะกับฉัน นี่น่าจะเป็นคำตอบ
GunWanderer

1
โปรดทราบว่าการใช้ContentWithTargetPathตัวแบ่งส่วนเพิ่มการคอมไพล์ (ทดสอบเมื่อ VS 2017 15.9.9)
Mads Ravn

26

เก็บไว้ใน$(ProjectDir)\Libแต่เพิ่มไฟล์เหล่านั้น " เป็นลิงก์ " ไปยังรูทของ. csproj ของคุณ ตอนนี้พวกเขาจะถูกคัดลอกไปยัง bin \ Debug (หรือโฟลเดอร์ผลลัพธ์อื่น ๆ ) โดยไม่ต้องอยู่ใน lib

แก้ไข: คำตอบนี้เขียนย้อนกลับไปเมื่อ ContentWithTargetPath ไม่พร้อมใช้งานในเวอร์ชันของ VS / MSBuild ที่ฉันใช้ ทิ้งคำตอบไว้ที่นี่สำหรับผู้ที่อาจต้องใช้ VS. เวอร์ชันเก่ากว่า โปรดหยุดแสดงความคิดเห็นเกี่ยวกับเรื่องนี้เราทุกคนรู้ว่ามีวิธีที่ดีกว่านี้


4
ขอบคุณ ananthonline. ฉันลองทำตามขั้นตอนของคุณแล้ว แต่ก็ไม่ได้ผล อาจเป็นฉันทำอะไรผิด นี่คือสิ่งที่ฉันกำลังทำโปรดแก้ไขหากคุณคิดว่ามีบางอย่างไม่ถูกต้อง: 1. ยกเว้น dll เหล่านั้นจากโปรเจ็กต์ แต่ปล่อยให้อยู่ใน lib 2 คลิกขวาที่โปรเจ็กต์และ "เพิ่มรายการที่มีอยู่" เลือก dll จาก lib และเพิ่ม "as link" 3. คลิกขวาที่ dlls แล้วเลือก "Copy Always" ใน "Copy to Output Directory" อีกครั้ง 4. ทำความสะอาดและสร้างใหม่ ผลลัพธ์: ฉันได้รับ dll เหล่านั้นอีกครั้งใน \ bin \ release \ lib
OhDear

1
โปรดโพสต์ภาพหน้าจอของโฟลเดอร์โซลูชันของคุณหลังจากกำหนดค่าแล้ว
Ani

3
ถ้าฉันพยายามเพิ่มลิงค์ไปยังไฟล์ที่มีอยู่แล้วใน
แผนผัง

1
เช่นเดียวกับ @Nyerguds ฉันพบว่าคุณไม่สามารถเพิ่มลิงก์ไปยังไฟล์ที่มีอยู่แล้วในโครงสร้างโครงการดังนั้นคำตอบนี้จึงไม่สามารถแก้ปัญหาได้
Tore Østergaard

1
มันไม่ท่วมรากของไดเร็กทอรีโครงการใน Solution Explorer หรือไม่? ด้วยไฟล์ดังกล่าวจำนวนมากอาจเป็นปัญหาได้ โดยปกติแล้วรูทของไดเร็กทอรีโปรเจ็กต์จะมีไฟล์ต่างๆมากเกินไปอยู่แล้ว
Alex34758

10

หากจุดประสงค์หลักของคุณคือการรวม DLL โดยไม่ทำให้ไดเร็กทอรีรากของโปรเจ็กต์ยุ่งเหยิงวิธีแก้ปัญหาอื่นคือการย้าย DLL ไปยัง Shared Project ที่แยกต่างหากและเพิ่มสิ่งนี้เป็นข้อมูลอ้างอิงในโปรเจ็กต์ดั้งเดิม

(โปรดทราบว่าโพสต์นี้ไม่ได้ตอบคำถามนี้โดยตรงเนื่องจากไม่ได้รักษาโฟลเดอร์และโครงสร้างโปรเจ็กต์ไว้ แต่ฉันพบว่าวิธีนี้มีประโยชน์เพราะฉันสามารถปรับโครงสร้างโครงการของฉันในกรณีของฉันและเพราะฉันต้องการหลีกเลี่ยงบางส่วนของ ข้อเสียของแนวทางอื่น ๆ ที่นี่)

ขั้นตอน

  • คลิกขวาที่ไฟล์ Solution -> Add -> New Project -> Shared Project
  • เพิ่ม DLL ในโปรเจ็กต์นี้ (ในไดเร็กทอรีรูทของโปรเจ็กต์นี้ไม่ใช่ในโฟลเดอร์ย่อย "lib")
  • (ตรวจสอบคุณสมบัติไฟล์ DLL ว่าตั้งค่าถูกต้องเช่นBuild Action: ContentและCopy to Output Directory: Copy Always)
  • คลิกขวาที่โครงการเดิม References -> Add Reference -> Shared Projects
  • เลือกโครงการที่แชร์ที่คุณสร้างไว้ก่อนหน้านี้

การตั้งค่ามีลักษณะดังนี้:

โซลูชัน-explorer-screenshot


2
วิธีแก้ปัญหาที่เรียบง่ายและสง่างามเพื่อให้โครงการไม่รก
Ravi Ganesh

ฉันไม่สามารถทำให้มันทำงานกับไฟล์ UAP และ * .bin ได้
Matteo

7

เพิ่มไฟล์ dll เป็นข้อมูลอ้างอิงไปยังโปรเจ็กต์และบนชุดการอ้างอิง "คัดลอกโลคัล" เป็น true


1
ขอบคุณ Erik ทำงานได้อย่างสมบูรณ์ยกเว้น dll หนึ่งรายการที่ฉันไม่สามารถเพิ่มเป็นข้อมูลอ้างอิงได้ ข้อผิดพลาดที่ฉันได้รับขณะเพิ่มเป็นข้อมูลอ้างอิงคือไม่สามารถเพิ่มการอ้างอิงถึง 'Libeay32.dll' โปรดตรวจสอบให้แน่ใจว่าไฟล์สามารถเข้าถึงได้และเป็นแอสเซมบลีหรือคอมโพเนนต์ COM ที่ถูกต้อง
OhDear

7
@MAnthony: เฉพาะแอสเซมบลี. NET หรือชุดประกอบการทำงานร่วมกันของ COM เท่านั้นที่สามารถเพิ่มเป็นข้อมูลอ้างอิงโครงการได้ DLL ดั้งเดิมไม่สามารถเป็นได้ คุณจะต้องหาวิธีอื่นในการคัดลอก DLL ไปที่ \ bin \ Release
Michael Liu

ขอบคุณ Erik และ Michael และ ananthonline ขออภัยไม่สามารถโหวตคำตอบและความคิดเห็นของคุณได้เนื่องจากฉันไม่มีคะแนนชื่อเสียงที่ต้องการ
OhDear

1
สำหรับ DLL ที่ไม่มีการจัดการคุณจะต้องใช้วิธีที่ฉันแนะนำด้านล่าง
Ani

4

หากคุณต้องการคัดลอกไฟล์จากไดเร็กทอรี Libs ไปยังรูทโฟลเดอร์ VS2017:

<ItemGroup Condition="'$(Platform)' == 'x64'">
    <None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

ไปยังโฟลเดอร์อื่น ๆ รวมถึงโฟลเดอร์ Libs (RecursiveDir)

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

3

ดูเหมือนใน VisualStudio 2015 ถ้า dll ที่คุณ 'เพิ่มด้วยลิงค์' อยู่ในโฟลเดอร์ย่อยของโปรเจ็กต์เดียวกันนั้นจะถูกใส่โฟลเดอร์โดยอัตโนมัติและผลลัพธ์จะถูกวางไว้ในโฟลเดอร์อย่างที่คุณเห็น

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


เหมือนกันใน VS2012 ปฏิเสธที่จะสร้างลิงก์และเพิ่มเป็นเนื้อหา ในท้ายที่สุดน่าเศร้าที่ทางออกที่ง่ายที่สุดคือการทิ้งลงในรูทโครงการ
Nyerguds

0

Noneวิธีอื่นเป็นเพียงการออกจากรายการที่เป็นชนิด ในการสำรวจวิธีการแก้ปัญหาให้คลิกที่คนที่คุณต้องการในการปรับใช้และการตั้งค่าคุณสมบัติการContentTrue

หมายเหตุ: ฉันทำสิ่งนี้ใน VS2019 และสิ่งต่างๆสามารถเปลี่ยนจากเวอร์ชันเป็นเวอร์ชันได้

เพื่อให้ได้ผลตอนนี้คลิกขวาที่โปรเจ็กต์ของคุณแล้วเลือก "ยกเลิกการโหลดโปรเจ็กต์" จากนั้นคลิกขวาที่โปรเจ็กต์ที่ยกเลิกการโหลดแล้วเลือก "แก้ไข project_name.vcxproj"

ในตัวแก้ไขไปที่ด้านล่างสุดของไฟล์และแทรกเป้าหมายนี้ก่อน</Project>แท็กต่อท้าย:

  <Target Name="CopyContent" AfterTargets="Build">
    <Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
  </Target>

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

ฉันยังตั้งค่าเป็นOutputDirectory:

$(SolutionDir)bin\$(Configuration)\$(Platform)\

และIntermediateDirectoryถึง:

$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\

ในหน้าคุณสมบัติทั่วไปของโครงการ สิ่งนี้ทำให้เอาต์พุตอยู่ในโฟลเดอร์ "bin" และตัวกลางในโฟลเดอร์ "obj" ในรูทของโซลูชันของคุณ

หมายเหตุ: $(SolutionDir)ไม่ได้กำหนดไว้เมื่อคุณเรียกใช้ MSBuild จากบรรทัดคำสั่ง มีเคล็ดลับที่คุณสามารถใช้เพื่อกำหนดให้กับโฟลเดอร์ที่ไฟล์. sln อาศัยอยู่โดยใช้ GetDirectoryNameOfFileAbove (เหลือไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน). นอกจากนี้ดูเหมือนว่าในปี 2019 พวกเขาจะจัดการสิ่งนี้อย่างถูกต้องในบรรทัดคำสั่งอยู่ดี ใช่ :)$(SolutionDir)มีเครื่องหมายต่อท้ายจึงไม่มีใครหลังจากที่มัน ผลลัพธ์ของแต่ละรายการต้องมีเครื่องหมายแบ็กสแลชต่อท้าย

ตอนนี้หากคุณเป็นเจ้าของ Pro หรือสูงกว่าโปรดอย่าทำเช่นนี้ทุกครั้งที่คุณต้องสร้างโครงการ นั่นจะเป็นง่อย Project -> Export Templateแต่เมื่อคุณมีการติดตั้งโครงการของคุณในแบบที่คุณชอบมันเลือก คุณตั้งชื่อให้และในครั้งต่อไปที่คุณต้องการสร้างโปรเจ็กต์เหมือนกับโปรเจ็กต์นั้นเพียงแค่เลือกชื่อนั้นในกล่องโต้ตอบโปรเจ็กต์ใหม่ (ในเวอร์ชันเก่าฉันคิดว่านี่คือFiles -> Export Teamplate...)


-1

ฉันมีปัญหาเดียวกันกับ Visual Studio 2010 / C # Project

สำหรับแอสเซมบลี (เช่นมีอินเทอร์เฟซ. NET) ให้ใช้โฟลเดอร์ "การอ้างอิง" ภายใต้โปรเจ็กต์ของคุณใน Solution Explorer คลิกขวาเลือก "เพิ่มรายการที่มีอยู่" และค้นหาชุดประกอบ. dll ของคุณ

ไฟล์. dll ทั่วไปสามารถวางไว้ในโฟลเดอร์ย่อย (ตามที่กล่าวไว้ข้างต้น "\ lib") และในคุณสมบัติให้เลือก:

  • Build Action = "HelpFiles"
  • คัดลอกไปยัง OutputDirectory = "ถ้าใหม่กว่า"

สิ่งนี้ใช้ได้ผลสำหรับฉันทุกประการตามที่ต้องการ - ในระหว่างการสร้างไฟล์. DLL จะถูกคัดลอกไปยังไดเร็กทอรีเอาต์พุตโดยไม่มีโฟลเดอร์ย่อย "\ lib"

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