Mit Powershell Archive erstellen
Für eine Funktionalität auf einem Buildserver wurde ein Skript benötigt, dass in der Lage ist, Archive zu erstellen. Ein idealer Anwendungsfall für Powershell, wenn man erst einmal ein paar wichtige Sachen erkannt hat.
Das Skript soll zwei Parameter empfangen. Der erste Parameter $destname enthält lediglich den Zielnamen des Archiv’s. Der zweite Parameter $source ist der Ordner, wo alle zu packenden Dateien abgelegt sind. {dest} und {temp} sind Platzhalter fester Pfade für das zu erstellende Archiv und temporäre Dateien.
param ([string] $destname, [string] $source) $path = "{dest}\" + $destname + ".zip" $temp = "{temp}" |
Um das Skript einfach einsetzen zu können, sollte in Powershell kein Modul mehr nachinstalliert werden müssen. Darum wurde auf die Funktionalität der gepackten Ordner von Windows zurückgegriffen. Diese gibt es schon geraume Zeit im Standard-Lieferumfang. Um diesen Ordner nutzen zu können, erstellt man ein leeres Archiv mittels einer kleinen Bytefolge, dass dann einfach wie ein Ordner angesprochen wird (mittels des COM-Objektes Shell.Application):
Set-Content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) $ShellApp = New-Object -ComObject Shell.Application $ZipPackage = $ShellApp.Namespace($path) |
Dieser Zwischenschritt löscht dem temporären Ordner und kopiert eine Auswahl von Dateien aus dem Quellverzeichnis in den frisch erstellen temporären Ordner:
rmdir $temp -Recurse -Force mkdir $temp $files = Get-ChildItem -Path $($source + "\*") -Include *.exe,*.dll | Copy-Item -Destination $temp mkdir $($temp + "\Data") $files = Get-ChildItem -Path $($source + "\Data\*") -Include *.* | Copy-Item -Destination $($temp + "\Data") |
Der letze Schritt war der schwerste: Als erstes wird der komplette temporäre Ordner einfach in das Archiv kopiert. Leider ist dieser Vorgang asynchron. Beendet man jetzt das Skript und die Powershell, so wird der Vorgang auch mit abgebrochen. Also muss man mittels Sleep solange warten, bis das Archiv garantiert erstellt ist. Diese Krücke ist zwar unbefriedigend, aber leider ist mir dafür keine alternative Lösung eingefallen:
$ZipPackage.CopyHere($temp, 4) Start-Sleep -s 15 |