Bei einem aktuellen Projekt benötigte ich die Möglichkeit, mehrere Werte aus einer XML-Datei mit einem ebenfalls darin definierten Logikoperator zu vergleichen. Das Szenario dazu: In dem Projekt ist eine leichtgewichtige Softwareverteilung auf Skriptbasis im Einsatz, die beim Systemstart verschiedene Applikationen aktualisiert. Hier war noch etwas mehr Logik erwünscht, um Aktivitäten nur dann auszuführen, wenn bestimmte Bedingungen erfüllt sind.
Da der Code möglichst dynamisch und gut erweiterbar sein sollte, stellte sich heraus, dass der Logikoperator durch einen Scriptblock dynamisch in den Code eingefügt werden musste. Um dies zu ermöglichen, habe ich die Funktion Apply-CustomLogic() entworfen, welche aktuell die Operatoren „like“, „is“, „isnot“, „startswith“, „notstartswith“, „endswith“ und „notendswith“ unterstützt.
Drei kurze Cmdlet Beispiele dazu, die mit einer Funktion auf dieser Basis arbeiten:
Apply-CustomLogic(„startswith“,“faq-o-matic.de“,“faq“) <- Ergebnis: $true
Apply-CustomLogic(„endswith“,“faq-o-matic.de“,“.de“) <- Ergebnis: $true
Apply-CustomLogic(„notendswith“,“faq-o-matic.de“,“.de“) <- Ergebnis: $false
Ein typisches Code-Szenario dafür wäre: Mehrere Konditionen sowie Referenzwerte müssen aus einer XML-Datei ausgelesen und dann in Powershell interpretiert werden.
Die XML Datei beinhaltet dann folgendes:
<check type="RegistryValue" logic="StartsWith"> <path>Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\TeamViewer\</path> <key>Version</key> <value>14</value> </check> <check type="RegistryPathPresent" logic="Is"> <path>Registry::HKEY_LOCAL_MACHINE\SOFTWARE\TeamViewer\</path> </check>
Der Script-Part dazu sähe wie folgt aus:
[..] #Check if a registry path is present if($checkType -eq "RegistryPathPresent"){ if( !(Apply-CustomLogic -condition $check.Logic -V1 $true -V2 (Get-ItemProperty -Path $Check.Path -ErrorAction SilentlyContinue)) ){ Write-CustomWarning("Check $checkType for $($Check.Path)$($check.Key) is $IgnoreSoftware, supposed value is $($Check.Value), current value is $($Path.$($Check.Key))") }else{ Write-CustomLog("Check $checkType for $($Check.Path)$($check.Key) is $IgnoreSoftware, supposed value is $($Check.Value), current value is $($Path.$($Check.Key))") } } #Check for a specific registry value if($checkType -eq "RegistryValue"){ if( !($Path = Get-ItemProperty -Path $Check.Path -ErrorAction SilentlyContinue) -or !(Apply-CustomLogic -condition $check.Logic -V1 $Path.$($Check.Key) -V2 $Check.Value) ){ Write-CustomWarning("Check $checkType for $($Check.Path)$($check.Key) is $IgnoreSoftware, supposed value is $($Check.Value), current value is $($Path.$($Check.Key))") }else{ Write-CustomLog("Check $checkType for $($Check.Path)$($check.Key) is $IgnoreSoftware, supposed value is $($Check.Value), current value is $($Path.$($Check.Key))") } } [..]
Hierbei werden nun die Konditionen und Referenzwerte aus der XML-Datei gegen reale, per Powershell abrufbare Funktion oder Variablen geprüft. Um den Code dynamisch zu generieren, nutzt die Funktion die Funktion Create([string]) auf der Klasse [Scriptblock], um aus einem vorher zusammengesetzten String einen ausführbaren Code zu generieren. Dieser Code wird im Anschluss durch $scriptblock.Invoke() ausgeführt und wendet den vorher generierten Logikcode aus.
Zu finden ist diese Funktion hier:
http://faq-o-matic.net/?p=8373