Kategorieauswahl

filter

XML-Abfrage Ereignisanzeige

Die Filter für die Windows Ereignisanzeige (Eventlog) sind sehr mächtig geworden. Mit den standard Optionen in der grafischen Oberfläche kann man schon viel machen, aber leider nicht im Nachrichtentext filtern. Das geht auch mit XML Abfragen. Klicken Sie dazu zunächst einmal auf ein ähnliches Ereignis und klicken Sie dort die Detailansicht an. Dort wählen Sie XML View:

Dann erstellen Sie einen benutzerdefinierten Filter und wählen dort den Reiter XML. Setzen Sie das Häkchen bei Abfrage manuell bearbeiten. Wenn Sie bereits bei Filter Reiter Einstellungen gemacht haben, sind diese auch schon im XML hier vordefiniert. Haben Sie z.B. das Anwendungslog ausgewählt steht dort:
<QueryList>
<Query Id=“0″ Path=“Application“>
<Select Path=“Application“>*</Select>
</Query>
</QueryList>
Oben habe ich Sie den XML-View auswählen lassen. Warum? Dort sehen Sie, wie die jeweiligen Felder nach denen Sie suchen können benannt sind. Um nun also z.B. nach dem Benutzernamen zu suchen ergänzen Sie die XML Zeilen wie folgt:
<QueryList>
Id=“0″ Path=“Security“>
<Select Path=“Security“>*</Select>
*[EventData[Data[@Name=‘TargetUserName‚] and (Data=‘s‚)]]
</Select>
</Query>
</QueryList>

Selbstverständlich dürfen Sie das gerne weiter verkomplizieren:
*[EventData[Data[@Name=’SubjectUserName‘] and (Data=’abc‘ or Data=’123’)]]
Dies würde alle mit der Angabe abc oder 123 finden bei UserName finden.

Möchten Sie in mehreren Logs suchen:
<Select Path=“Security“>*[System[(EventID=’1234′)]]</Select>
<Select Path=“Application“>*[System[(EventID=’4321′)]]</Select>
Würde alle Ereignisse aus dem Eventlog Security mit der ID 1234 und alle Ereignisse aus dem Applicationlog mit der ID 4321 anzeigen.

Um die Filter in der PowerShell zu nutzen können Sie die XML-Abfrage genauso in einen String schreiben und mit Get-WinEvent abfragen:
$Query=@“
<QueryList>
Id=“0″ Path=“Security“>
<Select Path=“Security“>
*[EventData[Data[@Name=’TargetUserName‘] and (Data=’s‘)]]
</Select>
</Query>
</QueryList>
„@
$Evts=Get-WinEvent -log Security -FilterXPath $Query -maxevents 1000

Schnelle Powershell Befehle anhand des Beispiels grep

Hier ein Quick&Dirty Beispiel wie man schnelle Powershellscripte schreibt um die eigenen Scripte ordentlich zu tunen. Unter Powershell gibt es zwar mit select-object und where-object als auch select-string einem grep aus dem UNIX- bzw. LINUX-Bereich ähnliche Befehle, doch so wirklich Bash-Gefühle kommen dabei nicht auf. Einen ersten Turbo können Sie einschalten, wenn Sie Parameter wie -inculde, -exclude oder -filter des jeweiligen Befehls verwenden, statt den Befehl alle Informationen beschaffen zu lassen und diese hinterher mit dem where-object auszuwerten. Vielleicht kennen Sie die Möglichkeit eine Funktion zu schreiben. Schneller funktioniert aufgrund des Streaming-Modus jedoch ein Filter. Wenn Sie dasselbe Script noch einmal mit dem Stichwort function statt filter einleiten können Sie das Laufzeitverhalten sehr schön überprüfen indem Sie den Befehl ls c: -recurse | grep suchbegriff aufrufen. Schauen Sie sich auch im Taskmanager ruhig einmal den Speicherverbrauch an!

filter grep ($suchbegriff) {
 $_  | out-string -stream | select-string $suchbegriff
 # Etwas aufwändiger, doch dafür werden die Objekte nicht als String, sondern nach wie vor als Objekt zurück gegeben mit folgender Zeile: # if (@($_  | out-string -stream | select-string $suchbegriff -simplematch).count -gt 0) {$_} }
Bei function wird der Befehl vor der Pipe erst einmal alle Daten (im obigen Beispiel alle Dateinamen) in einen Puffer schreiben. Erst wenn alle Dateien von Lw. C: im Puffer sind wird dieser an die Funktion nach der Pipe übergeben. Das out-string -stream hat damit allerdings nichts zu tun! Durch die Einleitung mit filter nimmt unser grep allerdings schon die Eingaben von ls entgegen sobal der erste Dateiname vorliegt. Die beiden Kommandos arbeiten also parallel. Das führt zu weniger Speicherverbrauch und zu schnelleren Ergebnissen.

Wer das Tuning auf die Spitze treiben möchte greift dennoch wieder zu einer Funktion. Denn filter schreibt auch eine function nur bettet er automatisch den kompletten Code in einen process Block ein. Das Beispiel:

function {
  process{
   # mein code
  }
}

ist also dasselbe wie:

filter {
  # mein code
}

In Ihrer Funktion gibt es aber vielleicht Dinge die nur 1 x zu Beginn und 1 x am Ende durchgeführt werden müssen, während die eigentliche Verarbeitung für alle übergebenen Objekte durchgeführt werden müssen. Bei einem filter würde immer komplett alles durchlaufen werden.

function {
  begin {
   # Hier könnten Sie z. B. den aktuellen Verzeichnispfad, oder andere Ausgangsbedingungen in eine Variable retten bevor Sie zu wüten anfangen
  }
  process {
   # Hier findet die eigentlich Verarbeitung statt. Möglicher Weise benutzen Sie cd um Verzeichnisse zu wechseln etc...
  }
  end {
   # Wechseln Sie wieder in das ursprüngliche Verzeichnis zurück geben Sie Variablen frei und führen Sie weitere "Aufräumvorgänge" durch
  }
}

Der Code bei begin würde also bei der ersten Objektübergabe erfolgen. Für alle weiteren Objekte würde nur noch der Code im Bereich process ausgeführt werden. Nach der Verarbeitung des letzten Objekts würde schließlich der Code unter end ausgeführt werden.

Möchten Sie Ihre Funktion dauerhaft verfügbar haben, sollten Sie diesen in eine Datei namens profile.ps1 schreiben und im Verzeichnis C:\Windows\System32\WindowsPowerShell\v1.0 ablegen, wenn er allen Benutzern des Computers zur Verfügung stehen soll. Wenn es nur für Ihren Benutzer sein soll, dann unter C:\Users\Ihr Benutzername\Documents\WindowsPowerShell.

Wenn Sie Daten von anderen Computern sammeln und auswerten, dann lassen Sie die Auswertung auf den anderen PCs laufen und holen Sie sich nur die Ergebnisdaten ab.

Langsam:

invoke-command {get-process} -computer name1,name2,name3 | where-object {$_.VM -gt 30MB} | sort PSComputerName | select Name,VM

Schnell:

invoke-command {get-process | select Name,VM | where-object {$_.VM -gt 30MB}} -computer name1,name2,name3 | sort PSComputerName

Des Weiteren gibt es für invoke-command den Parameter -throttlelimit. Dieser gibt an wieviele Computer gleichzeitig abgefragt werden. Der Standardwert ist 32. Je nach Aufgabe kann es sich lohnen mehr oder weniger Rechner anzugeben.

Der Befehl measure-command {Ihre Befehle oder Script} gibt Auskunft über die Zeit die Ihr Script zur Ausführung gebraucht hat.