Skip to the main content.

ScriptRunner Blog

AD-Objekte und mehr — durchsuche mit PowerShell die Eigenschaften komplexer Objekte

Inhaltsverzeichnis 

Post Featured Image

Bei der Arbeit mit PowerShell sind Sie wahrscheinlich schon auf Objekte mit besonders vielen Eigenschaften gestoßen. In solchen Fällen kann es schwierig sein, genau das zu finden, was gerade gebraucht wird. Häufig taucht das Problem z.B. bei  Windows Management Instrumentation (WMI)-Objekten oder Active Directory (AD)-Objekten auf. Wie lassen sich nun alle Eigenschaften finden, die eine bestimmte Zeichenfolge oder ein bestimmtes Muster enthalten? Wie können wir die Eigenschaften eines WMI-Objekts finden, die den Namen unseres Servers enthalten? Welche AD-Attribute enthalten den Nachnamen eines Benutzers? Lassen Sie uns eine PowerShell-Funktion zusammenstellen, die bei der Beantwortung dieser Fragen hilft!

Objekteigenschaften auflisten 

Einer der ersten Befehle, die ein PowerShell-Skriptanfänger lernt, ist Get-Member. Dieser Befehl zeigt uns die Attribute von Objekten an, einschließlich der Objekteigenschaften. Obwohl unsere Funktion sehr gut darauf aufbauen kann, wollen wir uns in diesem Fall eine Alternative ansehen, nämlich die in "psobject.properties" versteckten Attribute von Objekten. Der folgende Ausdruck listet die Eigenschaften des aktuellen PowerShell-Prozessobjekts auf (das Ergebnis ist zur besseren Lesbarkeit gekürzt):

get-process id

Hier sehen wir alle Eigenschaften mit ihren Namen, Typen und Werten. Es gibt noch einige weitere 'Untereigenschaften' ('properties of properties'), aber wir wollen uns auf diese drei konzentrieren. Wenn wir die Eigenschaftstypen betrachten, sehen wir, dass es einen Typ 'AliasProperty' gibt. Wir brauchen diese Art von Eigenschaften eigentlich nicht, da sie nur redundante Informationen anderer Eigenschaften speichern.

Lassen Sie uns eine Liste erstellen, welche die Eigenschaften unseres PowerShell-Prozessobjekts auflistet, die die Zeichenfolge "Windows" enthalten:

string Windows

 

Erstellen einer Search-Property-Funktion

Da wir bereits eine rudimentäre Lösung haben, fügen wir diese in eine Funktion ein und weisen ihr Parameter zu, nämlich ‑object und ‑pattern. Wir können unsere Objekte über die Pipeline suchen lassen, also sollte die Funktion Eingaben aus der Pipeline akzeptieren. Wir brauchen zudem eine foreach-Schleife, damit unsere Funktion auch mit einem Array von Objekten umgehen kann:



function Search-Property {
param(
[parameter(ValueFromPipeline)][psobject[]] $object,
[string] $pattern = "."
)
process{
foreach($o in $object){
$o.psobject.properties |
Where-Object {
$_.membertype -ne 'AliasProperty' -and
$_.value -match $pattern
} | Select-Object -Property @{n = "Object"; e = {$o.tostring()}}, Name, Value
}
}
}

 

Die Ergebnisse werden um eine neue Spalte erweitert, die die Darstellung des Eingabeobjekts als String enthält, so dass wir nachvollziehen können, zu welchem Objekt eine bestimmte Eigenschaft gehört. Dies ist wichtig, wenn wir mehrere Objekte betrachten. Wenn wir es nun ausführen, erhalten wir die gewünschten Ergebnisse:

Search-Property object

 

Die Leistungsfähigkeit der Funktion erhöhen 

Mit ein wenig Aufwand können wir die Funktion noch besser machen. Zunächst möchten wir vielleicht bestimmte Eigenschaften aus der Ergebnismenge ausschließen. Bei der Suche nach dem Vorkommen von "Nachname" unter den Eigenschaften eines AD-Benutzerkontos wollen wir beispielsweise nur diejenigen herausfiltern, die durch das Cmdlet Set-ADUser aktualisiert werden können. Möglicherweise möchten wir "distinguishedName" und "CN" ausschließen, da wir einen weiteren Befehl, Rename-ADObject, benötigen, um diese zu aktualisieren. Um bestimmte Eigenschaften auszuschließen, können wir den Parameter ‑ExcludeProperty verwenden, der ein Array von Zeichenketten mit Platzhaltern akzeptiert.

Möglicherweise möchten wir auch den Umfang der Eigenschaften einschränken, in denen wir suchen wollen. Wir möchten zum Beispiel nur in Eigenschaften suchen, die die Zeichenfolge "Name" enthalten. Dafür nutzen wir den Parameter Property, der ebenfalls ein Array von Zeichenfolgen mit Platzhaltern akzeptieren kann, um die Menge der Eigenschaften zu definieren, in denen gesucht werden soll. Wenn wir diesen Parameter nicht verwenden, werden standardmäßig alle Eigenschaften durchsucht.

Wir können unser Suchmuster auch auf die Namen der Eigenschaften anwenden. Dafür verwenden wir einen Switch-Parameter (SearchInPropertyNames). Vielleicht wollen wir auch nur in den Eigenschaftsnamen und nicht in den Eigenschaftswerten suchen, also können wir zusätzlich einen weiteren Switch-Parameter (ExcludeValues) verwenden.

Statt uns mit regulären Ausdrücken abzumühen, können wir auch literale Zeichenketten als Suchausdruck verwenden, indem wir einen Switch-Parameter LiteralSearch definieren.

Hier ist die verbesserte Funktion:



function Search-Property {
param(
[parameter(ValueFromPipeline)][psobject[]] $object,
[string] $pattern = ".",
[switch] $SearchInPropertyNames,
[switch] $ExcludeValues,
[switch] $LiteralSearch,
[string[]] $Property = "*",
[string[]] $ExcludeProperty
)
begin{
if($LiteralSearch -and $pattern -ne "."){
$pattern = [regex]::Escape($pattern)
}
}
process{
foreach($o in $object){
$o.psobject.properties |
Where-Object {
$propname = $_.name
$_.membertype -ne 'AliasProperty' -and
(
$(if(!$ExcludeValues){$_.value -match $pattern}) -or
$(if($SearchInPropertyNames){$_.name -match $pattern})
) -and
!($ExcludeProperty | Where-Object {$propname -like $_}) -and
($Property | Where-Object {$propname -like $_})
} | Select-Object -Property @{n = "Object"; e = {$o.tostring()}}, Name, Value
}
}
}

Die neue Funktion ist nur wenige Zeilen länger als die ursprüngliche. Der Kern der Funktion ist aber derselbe geblieben, sodass es sich lohnt, über mögliche komplexere Szenarien nachzudenken, in denen wir unsere Funktion verwenden und zusätzliche Funktionen hinzufügen könnten.

Hier ist die neue Funktion in Aktion. Im ersten Beispiel wollen wir die Eigenschaften der WMI-Objekte Win32_OperatingSystem und Win32_ComputerSystem anzeigen, die entweder die Zeichenfolge "DNS" oder den Namen unseres Computers enthalten. Außerdem wollen wir die Eigenschaften ausschließen, die mit zwei Unterstrichen beginnen, da sie nur Teil des WMI-Schemas sind:

win operating system objects

Im nächsten Beispiel kehren wir zum ursprünglichen Problem zurück. Sehen wir uns die AD-Benutzerattribute des Benutzerkontos an, die den Nachnamen enthalten, aber den "distinguishedName" und andere Namen ausschließen, die mit dem Cmdlet Rename-ADObject aktualisiert werden müssen:

get-ADUser identity

 

Wie geht es weiter? 

Natürlich könnten wir die Funktion weiter verbessern, indem wir Hilfetexte, Beispiele oder Erklärungen zu den Parametern hinzufügen. Es könnte eine Funktion geben, die dynamisch nach den Eigenschaften sucht, die Werte anderer Eigenschaften enthalten. Zum Beispiel könnte man nach allen Eigenschaften aller Benutzerkonten suchen, die den Nachnamen des aktuellen Benutzers enthalten.

Wir hoffen, dass Sie etwas Neues gelernt haben - oder zumindest ein neues praktisches Tool zu ihrem PowerShell-Toolkit hinzufügen können. Was sind Ihre Ideen, wie man diese Funktion verbessern kann?

 

 

Über den Autor: