In Ausgabeverzeichnis kopieren kopiert die Ordnerstruktur, möchte jedoch nur Dateien kopieren

87

Ich habe einen VS2008, den ich bestimmte Dateien aus einem Verzeichnis in meinen /bin/Ordner kopieren möchte . Ich habe die Dateien (in /common/browserhawk/) auf "In Ausgabeverzeichnis kopieren" gesetzt. Es wird jedoch auch die Ordnerstruktur kopiert: Die Dateien werden in kopiert/bin/common/browserhawk/

Wie bekomme ich diese Dateien zum Kopieren /bin/? Ich möchte diese nicht im Stammverzeichnis der Website speichern, damit sie korrekt kopiert werden.

Verwandte Frage: Visual Studio fügt dem Projekt nach dem Kompilieren .dll und .pdb hinzu

Steve Wright
quelle

Antworten:

59

Sie können ein Post-Build-Ereignis hinzufügen, um die Dateien zu kopieren.
Gehen Sie zu den Projekteigenschaften, Registerkarte "Ereignisse erstellen" und fügen Sie der Befehlszeile für Ereignisse nach dem Erstellen Folgendes hinzu:

copy "$(ProjectDir)\common\browserhawk\*.*" "$(TargetDir)"

Stellen Sie sicher, dass Sie die Anführungszeichen einfügen, wenn Ihr Projektpfad Leerzeichen enthält.

Bill A.
quelle
Vielen Dank für diesen Rat, da er auch in VS2012 für mich funktioniert hat.
Dib
2
Ich habe dies in meinem Fall leicht geändert:xcopy /s /d /y "$(ProjectDir)\stuff" "$(TargetDir)\stuff"
Danny Staple
44

Da ich frühere Antworten nicht kommentieren kann, werde ich die Lösung hier einfügen:

Fügen Sie Ihrer .csproj / .vbproj-Datei Folgendes hinzu, um @PaulAlexander bereitzustellen:

<ItemGroup>
    <AvailableItemName Include="RootContent">
      <Visible>false</Visible>
    </AvailableItemName>  
</ItemGroup>
<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

Auf diese Weise können Sie "RootContent" als Build-Aktion im Eigenschaftenfenster auswählen und auf alle kann über die GUI zugegriffen werden. Eine ausführlichere Erklärung: Mit der Option "AvailableItemName" wird im Wesentlichen eine neue Namensliste erstellt, der Sie Elemente im Projekt unter der Eigenschaft "Build Action" im Eigenschaftenfenster zuweisen können. Sie können diese neu erstellte Liste dann in einem beliebigen Ziel verwenden (z. B. über "@ (RootContent)").

Stoßwelle
quelle
Schöne Antwort, habe das selbst zum Erfolg genutzt!
Chris Marisic
Beachten Sie auch, dass VS 2010 (bei älteren Versionen nicht sicher) sich über AvailableItemNameein ungültiges Element beschwert , wenn Sie die Projektdatei in VS bearbeiten. Ignorieren Sie einfach die Warnung, es funktioniert trotzdem.
Aaronaught
2
Leider kopiert dies die Datei nur in das Ausgabeverzeichnis des Projekts, zu dem die Datei gehört - und nicht in das Ausgabeverzeichnis des Startprojekts. Dies ist wichtig, wenn Sie dies in einem Bibliotheksprojekt verwenden.
Sebastian Krysmanski
2
Dies funktioniert hervorragend für die Erstellung im Release- und Debug-Modus mit vs2008, scheint jedoch bei Verwendung der Veröffentlichung mit einem Klick nicht zu funktionieren. Irgendwelche Vorschläge?
Soenhay
2
Hat in vs2015 nicht für mich funktioniert. Behoben durch ein wenig Umschreiben des Ziels: <Target Name="RootOutputCopyTarget" AfterTargets="Build">... </ Target>
am
44

Wenn Sie .csproj / .vbproj in einem Texteditor bearbeiten, können Sie steuern, wo die Datei im Ausgabeverzeichnis abgelegt wird und welchen Namen die Datei im Ausgabeverzeichnis hat. Beispielsweise:

<None Include="content\someContent.txt">
  <Link>someContentInOutputDirectory.txt</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

Dies legen Sie die Datei content\someContent.txtin bin\someContentInOutputDirectory.txt. Sie können auch ein Unterverzeichnis in auswählen, binwenn Sie möchten. Fügen Sie es einfach dem Link-Element hinzu.

Daniel Yankowsky
quelle
3
Wow, hatte ich das Glück, das jetzt und nicht vor zwei Tagen zu brauchen. Vielen Dank; das ist toll!
Asherah
2
Oh mein Gott, danke. Ich habe gerade 6 Stunden damit verbracht, einen Eckmüll zu reparieren, bei dem VS DLLs nicht auf intelligente Weise kopiert hat. Dies ist die wahre Antwort auf das Leben, das Universum und alles.
Brandon
5
Dies ist bei weitem die beste Lösung
PhilHdt
1
Nachdem ich dies getan und das Projekt in Visual Studio neu geladen hatte, verschwanden die Abhängigkeitsdateien aus dem Lösungs-Explorer, als wären sie nicht im Projekt enthalten. Es wird jedoch weiterhin wie erwartet erstellt und wie gewünscht in die Ausgabe kopiert. Zur Umgehung füge ich derzeit jede Datei zweimal hinzu. einmal ohne Aktion und einmal mit 'In Ausgabe kopieren' gesetzt.
Éliette
1
Dies ist nicht die beabsichtigte Verwendung dieses Tags. In VS2013 wird beim Laden des Projekts eine Warnung ausgegeben, und die Datei wird beim Hinzufügen zum Projekt nicht angezeigt, da es sich um das Projektverzeichnis handelt.
jpmc26
15

Ich glaube, der XCOPY-Befehl verarbeitet Verzeichnisse und Dateien besser. Deshalb,

    XCOPY "$(ProjectDir)common/browserhawk" "$(TargetDir)" /E /I /F /Y

Dies ermöglicht das Erstellen von Ordnern außerhalb des Zielverzeichnisses.

    XCOPY "$(ProjectDir)Templates" "$(TargetDir)" /E /I /F /Y

Die Projektordner- / Dateistruktur von:

    A:\TEMP\CONSOLEAPPLICATION3\TEMPLATES
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt

Wird:

    A:\TEMP\CONSOLEAPPLICATION3\BIN\DEBUG
    │   ConsoleApplication3.exe
    │   ConsoleApplication3.pdb
    │   ConsoleApplication3.vshost.exe
    │   ConsoleApplication3.vshost.exe.manifest
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    │
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt
AMissico
quelle
/Dkann auch nützlich sein, um ein Überschreiben möglicher Änderungen zu vermeiden.
KurzedMetal
10

Fügen Sie Ihrer .csproj / .vbproj-Datei Folgendes hinzu

<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

Ändern Sie dann die Build-Aktion aller gewünschten Dateien im Stammordner in RootContent.

Paul Alexander
quelle
Nicht über die Dialoge ... aber Sie können Ihr Projekt in VS bearbeiten. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Projekt entladen. Klicken Sie dann mit der rechten Maustaste und wählen Sie Bearbeiten. Anschließend können Sie die MSBuild-Datei bearbeiten, die Ihr Projekt ist.
Paul Alexander
2
Danke, das sieht nützlich aus. Selbst wenn Ihr Snippet zur .vbproj-Datei hinzugefügt wurde, wird RootContentes leider nicht in der Dropdown-Liste "Build Action" angezeigt. Wenn Sie es manuell eingeben, wird in Visual Studio der Fehler "Eigenschaftswert ist ungültig" angezeigt. Was habe ich verpasst?
Heinzi
Funktioniert nicht mit dem Visual Studio 2010 C # -Konsolenanwendungsprojekt.
AMissico
Funktioniert nicht mit dem Visual Studio 2010 VB.NET-Konsolenanwendungsprojekt.
AMissico
Funktioniert nicht mit dem Visual Studio 2008 C # -Konsolenanwendungsprojekt.
AMissico
5

Ich habe dies in VS2010, VS2015, VS2017 und VS2019 verwendet. Ich bevorzuge diese Lösung, weil:

  1. Das XML kann in jedem Projekt wiederverwendet werden
  2. Der "RootContent" wird wie jeder andere "Inhalt" in der Visual Studio-Benutzeroberfläche als Build-Aktion ausgewählt.
  3. Das "CopyToOutputDirectory" wird genau wie erwartet eingehalten
  4. Der RootContent wird zur Projektausgabe hinzugefügt: Er wird durch Projektreferenzen übertragen, befolgt "Clean" usw.
  5. Der RootContent kann mit einem Platzhalter angegeben werden, wobei die rekursive Ordnerstruktur erhalten bleibt:
<RootContent Include="common\browserhawk\**">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</RootContent>

Gegen Anfang der Projektdatei:

  <ItemGroup>
    <AvailableItemName Include="RootContent">
      <!-- Add "RootContent" as a choice in the "Build Action" dropdown. -->
      <Visible>True</Visible>
    </AvailableItemName>
  </ItemGroup>

Aus dieser Antwort entlehnt

Nach dem Microsoft .targets-Import:

  <PropertyGroup>
    <AssignTargetPathsDependsOn>
      $(AssignTargetPathsDependsOn);
      IncludeRootContentAsContent;
    </AssignTargetPathsDependsOn>
  </PropertyGroup>
  <Target Name="IncludeRootContentAsContent">
    <CreateItem Include="@(RootContent)" AdditionalMetadata="TargetPath=%(RecursiveDir)%(Filename)%(Extension)">
      <Output ItemName="ContentWithTargetPath" TaskParameter="Include" />
    </CreateItem>
  </Target>

Aus dieser Antwort entlehnt

MattGerg
quelle
Das ist gut - ich würde austauschen, RootContentwas "hartcodiert" impliziert, CustomContentum anzuzeigen, dass dies spezialisierter Inhalt ist, den wir diesem Projekt hinzufügen und den wir auf diese spezielle Weise kopieren müssen. Nebenbei musste ich TargetPath=%(RecursiveDir)%(Filename)%(Extension)die Ordnerstruktur von den angegebenen CustomContentDateien zum Ausgabepfad neu erstellen .
Jonno
@Jonno Das Ziel besteht darin, die Datei (en) unabhängig von RecursiveDirectory direkt in das Stammausgabeverzeichnis zu kopieren. Die integrierte Build-Aktion "Inhalt" bietet uns bereits einen Mechanismus zum Kopieren unter Beibehaltung des RecursiveDirectory.
MattGerg
Ich hatte seit einiger Zeit keine Gelegenheit mehr, dies zu testen, aber würde das Festlegen der Build-Aktion "Inhalt" nicht dazu führen, dass Dateien unter /common/browserhawk/kopiert werden, /bin/common/browserhawk/wie im OP angegeben? IIRC, meine Absicht war es, in zu /common/browserhawk/a.txtlanden, /bin/a.txtaber eine Rekursion von dort nach unten zuzulassen, also /common/browserhawk/secret/stuff.pngendet in /bin/secret/stuff.png.
Jonno
@Jonno Ok, ja, das macht jetzt total Sinn. Ich habe die Antwort aktualisiert, um die einzuschließen %(RecursiveDirectory). Das ist wirklich cool, denn neben der Auswahl einzelner Dateien in der IDE können Sie auch mehrere Dateien mit Platzhaltern angeben. Bei Verwendung der** Platzhalters bleibt die gesamte Ordnerstruktur erhalten.
MattGerg
1
Vielen Dank für diese tolle Antwort! Ich denke, diese Antwort ist aus folgenden Gründen die richtige: 1. Keine externen cmds 2. plattformübergreifend
George Anisimov
2

Am Ende habe ich der Nant-Build-Datei einen Schritt hinzugefügt, der nach erfolgreicher Kompatibilität kopiert werden soll

<target name="action.copy.browserhawk.config" depends="compile.source">
    <copy todir="${App.Web.dir}/bin/" includeemptydirs="false">
        <fileset basedir="${browserhawk.config.dir}">
            <include name="bhawk_bb.dat" />
            <include name="bhawk_sp.dat" />
            <include name="browserhawk.properties" />
            <include name="maindefs.bdd" />
            <include name="maindefs.bdf" />
            <include name="BH_PRO.lic" />
        </fileset>
    </copy>
    <echo message="COPY BROWSERHAWK CONFIG: SUCCESS   ${datetime::now()}" />
</target>
Steve Wright
quelle
2
+1, weil dies für jemanden, der nant verwendet, immer noch eine hilfreiche Antwort ist
Chris Haines
1

Sie können eine Batchdatei erstellen, um die Dateien zu kopieren und als Ereignis nach dem Erstellen auszuführen.

jvanderh
quelle
Am Ende habe ich dies für eines meiner Projekte getan (obwohl ich ein Python-Skript anstelle einer Fledermaus verwendet habe).
Fire Lancer