14 min read
Microsoft Teams – 3. Teil der Graph PowerShell Reihe
MVP Damien Scoles berichtet über seine Erfahrungen mit Microsoft Graph. In seinem dritten Artikel geht er näher auf...
ScriptRunner Blog
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!
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):
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:
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:
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:
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:
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?
Okt 30, 2024 by Damian Scoles
MVP Damien Scoles berichtet über seine Erfahrungen mit Microsoft Graph. In seinem dritten Artikel geht er näher auf...
Okt 16, 2024 by Damian Scoles
Wie unterscheidet sich die Exchange Online-Administration mit dem Microsoft Graph PowerShell-Modul vom herkömmlichen...
Okt 8, 2024 by Damian Scoles
Die ein oder andere Hürde steht Nutzern im Weg, wenn sie anfangen Graph zu nutzen. In drei Teilen liefert Damian Hilfe....
Automatisierungs- und IAM (Identity and Access Management)-Architekt Tibor Soós ist ehemaliger PowerShell MVP und MCT. Er arbeitet derzeit bei der Firma Norks Hydro. Er ist leidenschaftlicher Dozent und Lehrer mit entsprechendem Abschluss, der sein Wissen gerne mit anderen teilt. Er ist der Autor eines kostenlosen, ungarischen Online-PowerShell-Buches und schreibt zu unterschiedlichen PowerShell Themen auf unserem Blog.