MSBuild Task-Syntax zum Löschen von Dateien

75

Ich versuche, eine MSBuild-Aufgabe zu schreiben, die das Obj-Verzeichnis und die PDBs aus meinem bin-Ordner in meinen Produktionserstellungsskripten löscht und anscheinend nicht richtig funktioniert.

Hat jemand ein Beispiel, wo er dies oder ähnliches tut, oder einen Link zu einem einfachen Beispiel zum Entfernen von Dateien und einem Verzeichnis mit MSBuild?

Chris Marisic
quelle

Antworten:

94

Wenn Sie ein gesamtes Verzeichnis löschen möchten, benötigen Sie die RemoveDir- Task:

<RemoveDir Directories="Path/To/Obj" />

Und wenn Sie die PDB-Dateien aus dem Bin löschen möchten, möchten Sie die Aufgabe Löschen :

<Delete Files="Path/To/Bin/MyApp.pdb" />

Beachten Sie, dass Sie in der Aufgabe Löschen keine Platzhalter verwenden können. Wenn Sie also mehrere PDF-Dateien haben, müssen Sie eine ItemGroup als Argument angeben .

Gavin Miller
quelle
8
Auf der Referenzseite zur RemoveDir- Aufgabe (siehe oben) wird angegeben, dass alle Dateien und Unterverzeichnisse gelöscht werden.
Yawar
Ich wünschte, ich könnte Ihre beiden Antworten markieren, da der Link zur RemoveDir-Aufgabe mir zeigte, was wirklich fehlte, war, dass ich meine OutputPath-Eigenschaft nicht dereferenziert habe, um das richtige Verzeichnis zu finden. Die Antwort von Sayeds mit der ItemGroup-Syntax war das, was ich tun musste, um alle PDFs abzurufen und sie zu löschen. Danke euch beiden!
Chris Marisic
1
Funktioniert für mich, also danke, aber es ist besser, ein ContinueOnError="true"Attribut für den ersten Wiederaufbau
hinzuzufügen
1
Nebenbemerkung - Wenn der Pfad länger als 260 Zeichen ist, schlägt RemoveDir fehl. und Sie müssen stattdessen Exec mit rmdir verwenden.
Ondrej Svejdar
Ich habe mit der <Delete Files=...>Aufgabe gespielt und festgestellt, dass beim Erstellen von Visual Studio die Dateien gelöscht werden und ich diese Informationen in der Ausgabe sehe. Aber wenn ich es ausführe, hat es eine msbuild-Befehlszeile, die Dateien werden nicht gelöscht und ich sehe nichts darüber in der Ausgabe, unabhängig von der Ausführlichkeit.
Howiecamp
130

Sie können zuerst die Dateien in diesen Verzeichnissen und dann das Verzeichnis selbst mit löschen

<Target Name="SomeTarget">
    <ItemGroup>
        <FilesToDelete Include="Path\To\Obj\**\*"/>
    </ItemGroup>   
    <Delete Files="@(FilesToDelete)" />   
    <RemoveDir Directories="Path\To\Obj\" />
</Target>
Sagte Ibrahim Hashimi
quelle
1
@pylover wo ich Path \ To \ Obj ** \ * habe, sollte der Pfad ein echter Ordnerpfad sein; Zum Beispiel C: \ temp \ Ordner zum Löschen. Könnte das der Grund sein, warum es bei Ihnen nicht funktioniert? Können Sie näher erläutern, warum es nicht funktioniert?
Sagte Ibrahim Hashimi
Mit 2012 habe ich gerade überprüft, ob RemoveDir das tut, was in den Dokumenten angegeben ist - Dateien und Ordner entfernt. Sollte die zusätzlichen Schritte nicht benötigen.
dudeNumber4
@SayedIbrahimHashimi Entschuldigung für den direkten Ansatz, aber ich habe Ihr Buch und kann immer noch keinen Weg finden, um dieses Problem zu umgehen. stackoverflow.com/questions/25525197/… . Kannst du helfen?
Blowsie
19

Posting für andere, die möglicherweise auf das gleiche Problem gestoßen sind, das ich hatte.

Die Aufgabe Löschen kann keine schreibgeschützten Dateien löschen, was ich tun musste, da die Dateien als schreibgeschützt markiert sind, wenn MSBuild von TFS auf den neuesten Stand gebracht wird. Ich habe den EXEC-Befehl verwendet, um schreibgeschützte Dateien zu löschen:

<ItemGroup>
    <FileToDelete Include="c:\temp\fileToDelete.txt"/>
</ItemGroup>
<Exec Command="del /F /Q &quot;@(FileToDelete)&quot;"/>
Garry Englisch
quelle
Dies ist das einzige, was für mich funktionieren würde, wenn die Dateien schreibgeschützt sind! (zB aus TFS ausgecheckt) :) Danke.
Tod Thomson
1
Ich hatte eine ItemGroup mit Platzhaltern, die auf so viele Dateien (vollständige Pfade) erweitert wurden, dass die delBefehlszeile zu lang wurde. Meine Lösung bestand darin, die Platzhalter deldirekt an eine ItemGroup zu übergeben, anstatt sie zu verwenden.
Jojo
8

Die veröffentlichten Antworten funktionieren so lange, wie Sie sich mit einem einzelnen Verzeichnis befassen müssen. Wenn Sie verschachtelte Ordner haben, RemoveDirschlägt dies mit einem Directory not emptyFehler fehl .

Ein leicht generischer Ansatz kümmert sich auch um verschachtelte Ordner:

<Target Name="CleanOutDir">
    <ItemGroup>
        <FilesToClean Include="$(OutDir)\**\*.*" />

        <!-- Bit of .Net to get all folders and subfolders -->
        <FoldersToClean Include="$([System.IO.Directory]::GetDirectories(&quot;$(OutDir)&quot;))" />
    </ItemGroup>

    <Delete Files="@(FilesToClean)"/>
    <RemoveDir Directories="@(FoldersToClean)" />
</Target>
Mrchief
quelle
5

Dieser Code ist so hässlich, dass er mit einem Airsickness-Beutel geliefert werden sollte. ;-) Aber es ist schnell, weil es keine Liste der zu löschenden Dateien usw. erstellt.

<Target Name="DeleteBuildFolder">
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
    <Exec Command="RmDir /S /Q &quot;$(BuildFolder)&quot;" />
</Target>

Wie viele RmDir-Befehle werden benötigt? Genug, damit einige RmDir-Befehle "Das System kann die angegebene Datei nicht finden" anstelle von "Das Verzeichnis ist nicht leer" zurückgeben. Auf meinem Computer scheint ein anderes RmDir erforderlich zu sein, wenn $ (BuildFolder) im Windows Explorer geöffnet ist. Das Antivirenprogramm kann RmDir wie gelegentlich Subversion betreffen, aber ich hätte lieber einen umfassenden AV-Schutz, als eine Ausschlussliste (falsch) zu verwalten.

Mark Jerde
quelle
4

Es ist auch möglich, zuerst die schreibgeschützte Eigenschaft aus der Datei zu entfernen und die msbuild-Löschaufgabe auszuführen.

Wie so:

<Target Name="DeleteFiles">
 <Message Text="Delete File" Importance="high"/>
 <Attrib Files="$(FileToDelete)" ReadOnly="false" />
 <Delete Files="$(FileToDelete)" />
</Target>`
Ole
quelle
2
Es sieht so aus, als ob die Attributaufgabe, auf die hier verwiesen wird, Teil des MSBuild Community Tasks- Projekts ist.
Scott Munro
2

Fügen Sie dies in Visual Studio 2013 am Ende meiner .csproj-Datei kurz vor dem </Project>schließenden Tag hinzu

<Target Name = "clean_folders" AfterTargets="Clean">
 <Exec Command = "rd /S /Q obj" />
 <Exec Command = "rd /S /Q bin" />
</Target>

Zuerst schien es nicht zu funktionieren, aber ich bemerkte, dass Visual Studio (oder R #, nicht sicher) erneut DesignTimeResolveAssemblyReferencesInput.cachezum obj-Ordner und der aktuelle \binOrdner hinzugefügt wurde (ich habe verschiedene Builds in verschiedenen Unterordnern unter \bin). Es hat alles andere entfernt, einschließlich der 25 anderen Build-Konfigurationen, die ich aus importierten .csproj-Dateien habe (ja, ich weiß).

Seien Sie vorsichtig, wenn Sie mehr als eine Konfiguration stapelweise neu erstellen, da nur alle vorherigen Bemühungen bei jeder Neuerstellung gelöscht werden und Sie nur die letzte haben. Whups.

CAD-Typ
quelle
1

Nur um noch eine Falte hinzuzufügen, die ich entdeckt habe. Ich verwende Visual Studio 2015. Die veröffentlichten Antworten, die per Platzhalter gelöscht werden, sind für mich immer noch problematisch. Ich vermute, dass die Platzhalter vor dem Build ausgewertet werden, nicht danach . Das bedeutet, dass das Löschen nicht erfolgt, wenn die zu löschenden Dateien während des Builds erstellt werden. Es führt auch zu einem wunderbaren Verhalten, bei dem das Löschen bei jeder zweiten Erstellung funktioniert, was das Testen sehr angenehm macht.

Ich gebe Platzhalter auf. Für das, was ich tue, kenne ich die Dateien, die Probleme verursachen, und ich codiere die tatsächlichen Dateinamen fest (wenn man das innerhalb einer Projektdatei so nennen kann).

rrreee
quelle
1
Befindet sich die ItemGroup, die die Platzhalter verwendet, innerhalb des Ziels, sollte sie bei jeder Ausführung des Ziels ausgewertet werden. ItemGroups auf Projektebene werden tatsächlich ausgewertet, wenn das Projekt ausgeführt wird.
Zastai