Visual Studio: Wie kopiere ich in das Ausgabeverzeichnis, ohne die Ordnerstruktur zu kopieren?

111

Ich habe ein paar DLL-Dateien im Ordner \ lib meines Projektordners. Auf der Eigenschaftsseite von dll habe ich "Aktion erstellen" als "Inhalt" und "In Ausgabeverzeichnis kopieren" als "Immer kopieren" ausgewählt.

Nach dem Build wird die DLL tatsächlich kopiert, aber sie befinden sich in \ bin \ Release \ lib und nicht in \ bin \ Release.

Gibt es eine Möglichkeit, DLL-Dateien nach \ bin \ Release (und nicht nach \ bin \ Release \ lib) zu kopieren, ohne ein Post-Build-Skript zu schreiben oder auf nant usw. zurückzugreifen?

Ach je
quelle

Antworten:

255

anstatt den Zielpfad wie folgt zu <Content>verwenden <ContentWithTargetPath>und anzugeben:

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

Beachten Sie, dass dieser Eintrag in Visual Studio (2012, 2015, 2017) möglicherweise nicht sichtbar ist. Sobald er manuell zum csproj hinzugefügt wurde, wird er in Visual Studio angezeigt. Der Zielpfad kann jedoch nicht über die Benutzeroberfläche bearbeitet werden.

Daniel Zeitlin
quelle
2
Ich sehe ContentWithTargetPath in VS 2015 nicht als Build-Aktionsoption. Gibt es eine Möglichkeit, es hinzuzufügen?
Kim
1
Nachdem ich den Eintrag manuell in die .csproj-Datei eingefügt habe, wird er als Option in der IDE angezeigt. Ich kann den Zielpfad jedoch immer noch nicht in der IDE bearbeiten.
Kim
9
Ich mache mir nur Sorgen, dass dies bei zukünftigen Versionen von MSBuild / .NET / Visual Studio / Whatever nicht mehr unterstützt wird, da die VS2015-Benutzeroberfläche diese Option oder die TargetPath-Eigenschaft nicht anzeigt.
MarioDS
1
Das funktioniert bei mir. Keine der anderen Antworten funktioniert für mich. Dies sollte die Antwort sein.
GunWanderer
1
Beachten Sie, dass die ContentWithTargetPathinkrementelle Kompilierung von Pausen (getestet am VS 2017 15.9.9)
Mads Ravn
26

Behalten Sie sie bei $(ProjectDir)\Lib, aber fügen Sie diese Dateien " Als Link " zum Stammverzeichnis Ihrer .csproj hinzu. Jetzt werden sie in bin \ Debug (oder einen anderen Ausgabeordner) kopiert, ohne sich in lib zu befinden.

BEARBEITEN: Diese Antwort wurde vor langer Zeit geschrieben, als ContentWithTargetPath in den von mir verwendeten Versionen von VS / MSBuild nicht verfügbar war. Lassen Sie diese Antwort hier für Personen, die möglicherweise eine ältere Version von VS verwenden müssen. Bitte hören Sie auf, dies zu kommentieren. Wir alle wissen, dass es jetzt bessere Möglichkeiten gibt.

Ani
quelle
4
Danke ananthonline. Ich habe deine Schritte ausprobiert, aber es hat nicht geholfen. Vielleicht mache ich etwas falsch. Folgendes mache ich, bitte korrigieren Sie, wenn Sie der Meinung sind, dass etwas nicht stimmt: 1. Schließen Sie diese DLLs aus dem Projekt aus, lassen Sie sie jedoch in lib. 2. Klicken Sie mit der rechten Maustaste auf das Projekt und klicken Sie auf "Vorhandene Elemente hinzufügen". Wählen Sie die DLLs aus lib aus und fügen Sie sie "als Link" hinzu. 3. Klicken Sie mit der rechten Maustaste auf die DLLs und wählen Sie erneut "Immer kopieren" in "In Ausgabeverzeichnis kopieren". 4. Reinigen und neu erstellen. Ergebnis: Ich habe wieder diese DLLs in \ bin \ release \ lib
OhDear
1
Bitte posten Sie einen Screenshot Ihres Lösungsordners nach der Konfiguration
Ani
3
Wenn ich versuche, einen Link zu einer Datei hinzuzufügen, die bereits im Projektbaum enthalten ist, wird diese abgelehnt und stattdessen nur wieder in das Projekt aufgenommen ...
Nyerguds
1
Wie bei @Nyerguds habe ich das Gefühl, dass Sie einer Datei, die sich bereits im Projektbaum befindet, keinen Link hinzufügen können, sodass diese Antwort die Frage nicht löst.
Tore Østergaard
1
Überflutet es nicht das Stammverzeichnis des Projektverzeichnisses im Projektmappen-Explorer? Bei vielen solchen Dateien kann dies ein Problem sein. Normalerweise enthält das Stammverzeichnis eines Projektverzeichnisses bereits zu viele verschiedene Dateien.
Alex34758
10

Wenn Sie hauptsächlich DLLs einbinden möchten, ohne das Projektstammverzeichnis zu überladen, besteht eine andere Lösung darin , die DLLs in ein separates freigegebenes Projekt zu verschieben und diese als Referenz in das ursprüngliche Projekt einzufügen.

(Beachten Sie, dass dieser Beitrag diese Frage nicht direkt beantwortet, da er die Ordner- und Projektstruktur nicht beibehält. Ich fand diesen Ansatz jedoch nützlich, weil ich mein Projekt in meinem Fall umstrukturieren konnte und einige der Probleme vermeiden wollte Nachteile der anderen Ansätze hier.)

Schritte

  • Klicken Sie mit der rechten Maustaste auf Ihre Solution -> Add -> New Project -> Shared Project
  • Fügen Sie die DLLs zu diesem Projekt hinzu (im Stammverzeichnis dieses Projekts, nicht in einem Unterordner "lib").
  • (Überprüfen Sie, ob die Eigenschaften der DLL-Datei richtig eingestellt sind, z. B. Build Action: Contentund Copy to Output Directory: Copy Always)
  • Klicken Sie mit der rechten Maustaste auf das ursprüngliche Projekt References -> Add Reference -> Shared Projects
  • Wählen Sie das zuvor erstellte freigegebene Projekt aus

Das Setup sieht folgendermaßen aus:

Lösungs-Explorer-Screenshot

Sonny
quelle
2
Bei weitem die einfache und elegante Lösung, um das Projekt übersichtlich zu halten.
Ravi Ganesh
Ich konnte es nicht mit UAP- und * .bin-Dateien zum Laufen bringen.
Matteo
7

Fügen Sie die DLL-Dateien als Referenz zum Projekt hinzu und setzen Sie im Referenzsatz "Copy local" auf true.

erik_nw
quelle
1
Danke Erik. Das funktioniert perfekt, bis auf eine DLL, die ich nicht als Referenz hinzufügen kann. Der Fehler, den ich beim Hinzufügen als Referenz erhalte, ist Ein Verweis auf 'libeay32.dll' konnte nicht hinzugefügt werden. Stellen Sie sicher, dass auf die Datei zugegriffen werden kann und dass es sich um eine gültige Assembly- oder COM-Komponente handelt.
OhDear
7
@MAnthony: Nur .NET-Assemblys oder COM-Interop-Assemblys können als Projektreferenzen hinzugefügt werden. native DLLs können nicht sein. Sie müssen einen anderen Weg finden, um die DLL nach \ bin \ Release zu kopieren.
Michael Liu
Danke Erik und Michael und ananthonline. Leider können Sie Ihre Antworten und Kommentare nicht verbessern, da ich nicht die erforderlichen Reputationspunkte habe.
OhDear
1
Für die nicht verwaltete DLL müssen Sie die unten vorgeschlagene Methode verwenden.
Ani
4

Wenn Sie Dateien aus dem Libs-Verzeichnis in den Stammordner VS2017 kopieren müssen:

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

In jeden anderen Ordner, einschließlich Libs (RecursiveDir)

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

In VisualStudio 2015 scheint es so zu sein, dass die DLLs, die Sie mit einem Link hinzufügen, in einem Unterordner desselben Projekts gespeichert werden. Sie werden automatisch in einen Ordner verschoben, und die Ausgabe wird auch in einem Ordner abgelegt, den Sie gesehen haben.

Wenn sich die DLLs in einem anderen Projekt oder Verzeichnis auf der Festplatte befinden, das sich nicht in einem Unterordner des Projekts befindet , können Sie 'Mit einem Link hinzufügen ', und sie werden problemlos in das Stammverzeichnis gestellt.

DefenestrationDay
quelle
Gleiches gilt für VS2012. Es weigert sich, sie zu einem Link zu machen, und fügt sie nur als Inhalt hinzu. Am Ende scheint es leider die einfachste Lösung zu sein, sie im Projektstamm abzulegen.
Nyerguds
0

Eine alternative Methode besteht darin, die Elemente nur als Typ zu belassen None. Klicken Sie im Lösungs-Explorer auf diejenigen, die Sie bereitstellen möchten, und legen Sie die ContentEigenschaft fest True.

Hinweis: Ich habe dies in VS2019 getan und die Dinge können sich von Version zu Version ändern.

Damit dies funktioniert, klicken Sie jetzt mit der rechten Maustaste auf Ihr Projekt und wählen Sie "Projekt entladen". Klicken Sie dann mit der rechten Maustaste auf das entladene Projekt und wählen Sie "Projektname.vcxproj bearbeiten".

Gehen Sie im Editor bis zum Ende der Datei und fügen Sie dieses Ziel direkt vor dem nachfolgenden </Project>Tag ein:

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

Klicken Sie nun mit der rechten Maustaste auf das entladene Projekt und wählen Sie "Projekt neu laden". Wählen Sie zum Speichern und Schließen, wenn Sie dazu aufgefordert werden.

Ich habe auch Folgendes eingestellt OutputDirectory:

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

und das IntermediateDirectoryzu:

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

auf der Seite Projekteigenschaften Allgemein. Dadurch wird die Ausgabe in einem "bin" -Ordner und die Zwischenprodukte in einem "obj" -Ordner im Stammverzeichnis Ihrer Lösung abgelegt.

Hinweis: $(SolutionDir)Dies ist nicht definiert, wenn Sie MSBuild über die Befehlszeile ausführen. Mit GetDirectoryNameOfFileAbove können Sie diesen Trick in einem Ordner definieren, in dem sich die SLN-Datei befindet. (links als Übung für den Leser). Es sieht auch so aus, als würden sie 2019 in der Kommandozeile sowieso richtig damit umgehen. Ja :) Das $(SolutionDir)enthält einen nachgestellten Backslash, daher keinen danach. Die Ergebnisse müssen jeweils einen nachgestellten Backslash aufweisen.

Wenn Sie Pro oder höher besitzen, tun Sie dies bitte nicht jedes Mal, wenn Sie ein Projekt erstellen müssen. Das wäre lahm. Wählen Sie stattdessen, sobald Sie Ihr Projekt so eingerichtet haben, wie Sie es möchten Project -> Export Template. Sie geben ihm einen Namen und wenn Sie das nächste Mal ein Projekt wie dieses erstellen möchten, wählen Sie diesen Namen einfach im Dialogfeld "Neues Projekt". (In der älteren Version war das meiner Meinung nach so Files -> Export Teamplate....)

ChuckEng
quelle
-1

Ich hatte das gleiche Problem mit Visual Studio 2010 / C # Project.

Verwenden Sie für Assemblys (dh mit der .NET-Schnittstelle) den Ordner "Referenzen" unter Ihrem Projekt im Projektmappen-Explorer. Klicken Sie mit der rechten Maustaste darauf, wählen Sie "Vorhandenes Element hinzufügen" und suchen Sie Ihre DLL-Assembly.

Allgemeine DLL-Dateien können in einem Unterordner abgelegt werden (wie oben erwähnt "\ lib") und in den Eigenschaften Folgendes auswählen:

  • Build Action = "Hilfedateien"
  • In OutputDirectory kopieren = "Wenn neuer"

Dies funktionierte bei mir genau wie gewünscht - während des Builds werden die DLLs ohne den Unterordner "\ lib" in das Ausgabeverzeichnis kopiert.

Petr Hendl
quelle