Archiv

Archiv für April, 2011

dotnet-snippets.de wird 5 Jahre alt

24. April 2011 Keine Kommentare

Die Webseite dotnet-snippets.de wird 5 Jahre alt. Herzlichen Glückwunsch!

Wer die Seite noch nicht kennt, aber mit Microsoft .NET entwickelt, sollte einfach mal vorbeischauen. Es gibt viele kurze hilfreiche Codeschnipsel zu den meisten Problemchen, die man so im täglichen Leben hat.

KategorienAllgemein, Microsoft .NET Tags:

Mit Powershell Archive erstellen

14. April 2011 Keine Kommentare

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
KategorienAllgemein Tags: ,

Alte Daten mittels Powershell löschen

13. April 2011 1 Kommentar

In einem Backup-Ordner stand die Aufgabe an, alte Dateien automatisch löschen zu lassen. Dazu wurde folgendes Skript eingesetzt:

Get-ChildItem -Path . |
  Where-Object -FilterScript {($_.LastWriteTime -lt [DateTime]::Now.AddDays(-7))} |
  Remove-Item -force

Zuerst werden alle relevanten Dateien ermittelt. Danach wird auf diese Liste ein Filter gesetzt, der nur Dateien ermittelt, die älter als 7 Tage sind. Hierzu wird eine Rückgriff auf DateTime aus dem Net-Framework genutzt. Es bietet mit Now und AddDays die gewünschte Funktionalität, von jetzt 7 Tage nach hinten zu gehen. Als letzten Schritt muss die ermittelte Liste lediglich an Remove-Item weitergereicht werden.

PSSecurityException, obwohl in Powershell die Ausführung von Skripten erlaubt wurde

13. April 2011 1 Kommentar

Beim Ausführen einer Powershell-Datei erhielt ich im Protokoll neulich folgende bekannte Fehlermeldung, obwohl Set-ExecutionPolicy auf RemoteSigned gesetzt war:

Die Datei "...test.ps1" kann nicht geladen werden, da die Ausführung
 von Skripts auf diesem System deaktiviert ist. Weitere
 Informationen erhalten Sie mit "get-help about_signing".
Bei Zeile:1 Zeichen:2
+ . <<<<  '...test.ps1'
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

Die Lösung lag letztendlich darin, dass das entsprechende Skript auf einem 64Bit-System als 32Bit-Task aufgerufen wurde. Es war ausreichend, Set-ExecutionPolicy unter Powershell (x86) ebenfalls aufzurufen und entsprechend zu setzen.