Category: SCCM

Powershell: Computer zwischen Collections verschieben

Ihr habt sicher auch schon (mehr als) einmal vor der Anforderung gestanden, Computerkonten in oder aus einer Sammlung aufzunehmen bzw. zu entfernen. Bei einzelnen Computerkonten ist das sicherlich einfach über die ConfigMgr Console zu lösen, doch sind mehrere Computerkonten betroffen, kann es doch recht aufwendig werden!

Vor kurzem bekam ich eine Anforderung, bei der ich wieder vor einer ähnlichen Problemstellung stand und habe zur Powershell gegriffen. Was dabei heraus gekommen ist, möchte ich euch mit diesem Artikel gerne näher erläutern.

Die Grundlagen

Bevor wir uns den eigentlichen Scripts widmen, noch ein paar Grundlagen:

Collection Memberships

Die Inhalte einer Collection, werden über sogenannte Collection Memberships definiert. Dabei werden nicht die Resources selbst, sondern Collection Membership Rules hinzugefügt bzw. entfernt.

Aus der ConfigMgr Console kennt ihr sicher die verschiedenen Varianten:

Variante Beschreibung
Direct Membership Eine “direkte Mitgliedschaft”, bezogen auf genau eine Resource, die über den Namen – eindeutig – gefiltert wird.
Query Based Membership In diesem Fall werden die Mitglieder über eine Abfrage (WQL) bestimmt. Alle Ergebnisse werden als Mitglieder übernommen.
Include Collection Membership Bei dieser Variante wird eine weitere Collection und damit deren Inhalt, vollständig übernommen. Verändert sich der Inhalt der verknüpften Liste, nimmt dies auch Auswirkung auf die betroffene Collection. Diese Variante kann auch als white listening verstanden werden.
Exclude Collection Membership Diese Art ist vergleichbar mit der Include Collection Membership, mit einem Unterschied: Alle Resources der verknüpften Collection, wird aus der betroffenen Collection ausgeschlossen. Auch in diesem Fall beeinträchtigen Änderungen an der “exkludierten” Collection, den Inhalt der betroffenen Collection. Diese Variante kann als eine Art: black listening gesehen werden.

In unserem Fall nutzen wir die Direct Membership Rule um einzelne Geräte in eine Collection aufzunehmen bzw. aus dieser zu entfernen.

WMI Klassen

  • SMS_Collection
  • SMS_CollectionRuleDirect

    Die WMI Klasse SMS_CollectionRuleDirect entspricht einem Collection Membership Rule Eintrag. Wenn wir später die Collection Mitgliedschaften programmatisch bearbeiten, nutzen wir die Instanz dieser Klasse, um den gewünschten Eintrag aus der Collection zu entfernen bzw. einen neuen hinzuzufügen.

  • SMS_R_System

    Eine Instanz dieser Klasse entspricht den Computer- bzw. Geräteinformationen (System Resource).

Die Lösung

Wie üblich, habe ich zur Lösung wieder auf Powershell zurückgegriffen. In diesem Fall habe ich die ConfigMgr Powershell Cmdlets nicht genutzt, sondern bin direkt über die WMI Schnittstelle gegangen. Aber keine Sorge, alles auf Basis des offiziellen ConfigMgr SDK.

Wie bereits angesprochen, werden die Mitgliedschaften über die Collection Membership Rules definiert. Zum Hinzufügen oder Entfernen, werden nicht die Resources direkt, sondern die entsprechenden Rules bearbeitet.

Bevor wir in die Umsetzung gehen, schauen wir uns kurz noch an, wie wir diese Regel erstellen bzw. verwenden.

Die SMS_CollectionRuleDirect-Instanz

Im ersten Schritt, erstellen wir uns eine neue (leere) Instanz der Klasse SMS_CollectionRuleDirect, um eine direkte Zuordnung einer bestimmten Resource zu verändern. Danach legen wir durch setzen der Eigenschaften fest, welche Resource und Collection wir verändern wollen.

Werfen wir einen Blick auf die Eigenschaften, die wir setzen wollen:

Eigenschaft Beschreibung/ Wert
ResourceClassName Dieser Wert gibt an, für welche (Ziel)Ressource die Regel gilt. Mögliche Werte sind SMS_R_SYSTEM für Geräte- oder SMS_R_USER für Benutzer-Ressourcen.
ResourceID Über die ResourceID wird das gewünschte Geräte- oder Benutzerobjekt (SMS_R_Systen, SMS_R_User) ausgewählt, welches über die Regel in die Collection aufgenommen werden soll.
RuleName Dieser Wert setzt den Namen der Regel. Bei einer direkten Regel (SMS_CollectionRuleDirect) wird hier der Ressourcenname verwendet.

Ein Beispiel:

# Get SMS_R_System by Name

$resource = Get-WmiObject -Class SMS_R_System -Filter "Name = 'TGC-DEV-001'" -ComputerName $SiteServer -Namespace $Namespace

Output:

Name         ResourceID
----         ----------
TGC-DEV-001  16777219

Demnach würde dann die Regel mit den folgenden Werten erstellt werden:

# Get SMS_CollectionMembershipRule instance
$rule = ([WMIClass]"\\$SiteServer\root\sms\site_$($siteCode):SMS_CollectionRuleDirect").CreateInstance();

# Set rule properties
$rule.ResourceClassName = "SMS_R_System";
$rule.ResourceID = $resource.ResourceID;    # 16777219
$rule.Rulename = $resource.Name;            # TGC-DEV-001

Das Powershell Script

Endlich! Kommen wir zur Umsetzung. Nochmal zur Erinnerung: “Wir wollen eine (System)Ressource, von einer Collection, in die andere verschieben.”

Ausgangssituation

Objekt WMI Class Instance Name
Endgerät  SMS_R_System TGC-DEV-001
Quellsammlung SMS_Collection Microsoft Quality Updates 2019.04
Zielsammlung SMS_Collection Microsoft Quality Updates 2019.05

1. Get-WmiObject -Class SMS_Collection

Im ersten Schritt lesen wir die Quellsammlung (SMS_Collection) aus dem ConfigMgr. Damit erhalten wir die Quelle, aus der wir das Endgerät entfernen:

# 1. Get SMS_Collection (Source)..
$collection = Get-WmiObject -Query "SELECT * FROM SMS_Collection WHERE Name='Microsoft Quality Updates 2019.04'" -ComputerName $SiteServer -Namespace $namespace

2. Get-WmiObject -Class SMS_R_System

Im nächsten Schritt suchen wir uns das Endgerät bzw. die System Resource heraus. Damit erhalten wir den ComputerName und ResourceID, welches wir für das erstellen der SMS_CollectionDirectRule benötigen.

# 2. Get SMS_R_System
$resource = Get-WmiObject -Query "SELECT * FROM SMS_R_System WHERE Name='TGC-DEV-001'" -ComputerName $SiteServer -Namespace $namespace

3. SMS_CollectionMembershipDirectRule

Jetzt erstellen wir noch eine neue Instanz der Klasse SMS_CollectionMembershipDirectRule und setzen die Eigenschaften des Endgerätes (s. Schritt 2. Get-WmiObject -Class SMS_R_System):

# 3. Create SMS_CollectionRuleDirect Instance
$rule = ([WMIClass]"\\$SiteServer\root\sms\site_$($siteCode):SMS_CollectionRuleDirect").CreateInstance();

# 3.1 Set rule properties
$rule.ResourceClassName = "SMS_R_System";
$rule.ResourceID = $resource.ResourceID;
$rule.Rulename = $resource.Name;

4. DeleteMembershipRule

Mit den Informationen der Collection und der MembershipRule, können wir den den ersten Teil des “Verschiebens” durchführen: Das Entfernen des Endgerätes aus der Quellsammlung.

Hierfür bietet die Instanz der Klasse SMS_Collection eine Methode an: DeleteMembershipRule. Dieser Methode übergeben wir unsere neue SMS_CollectionMembershipDirectRule. Als Rückgabe erhalten wir eine ResultObject, welches einen ErrorCode beinhaltet. (0 = Success).

# 4.2.2 Delete rule from memberships.
$resultObject = $collection.DeleteMembershipRule($rule);

# ReturnValue = 0 means: success.
$errorCode = $resultObject.ReturnValue;

5. AddMembershipRule

Nachdem wir erfolgreich das Endgerät aus der Quellsammlung entfernt haben, können wir dieses jetzt in die Zielsammlung aufnehmen. Dazu lesen wir (wieder) die Collection aus dem ConfigMgr aus. Nur dieses Mal suchen wir nach der Zielsammlung:

# 5. Get SMS_Collection (Target)..
$targetCollection = Get-WmiObject -Query "SELECT * FROM SMS_Collection WHERE Name='Microsoft  Quality Updates 2019.05'" -ComputerName $SiteServer -Namespace $namespace

Die SMS_Collection bietet eine weitere Methode, die wir zur Aufnahme einer neuen Regel nutzen können: AddMembershipRule, die ebenfalls als Parameter eine Instanz der Klasse SMS_CollectionMembershipRule annimmt. Wir können die gleiche Instanz nehmen, die wir auch für das Entfernen aus der Quellsammlung genutzt haben:

# 6. Add rule to collection members.
$resultObject = $targetCollection.AddMembershipRule($rule);

# ReturnValue = 0 means: success.
$errorCode = $resultObject.ReturnValue;

Finally ..

Congratulations! Damit haben wir erfolgreich ein Endgerät, zwischen zwei Collections verschoben.

Anmerkungen

Bevor eine MembershipRule entfernt oder hinzugefügt wird, empfehle ich euch vorher zu prüfen, ob diese Regel (bereits) existiert. Dadurch vermeidet ihr eine Exception beim Ausführen der Methoden. Leider liefern keine expliziten ErrorCode für den Status “Exists” bzw. “NotExists”.

Die Prüfung ist recht simple und durch eine weitere WMI Abfrage zu lösen. Bspw. so:

# 4.2.1 Resource is a member?
$memberExists = Get-WmiObject -Class SMS_FullCollectionMembership -ComputerName $SiteServer -Namespace $namespace | Where-Object { ($_.CollectionID -eq $collection.CollectionID) -and ($_.ResourceID -eq $resource.ResourceID) }

Falls bereits eine Regel existiert, bekommt ihr als Rückgabe dieser Abfrage die passende SMS_CollectionMembershipRule, die ihr sonst auch manuell gebaut hättet.

Keep PoSh-ing IT!

/Ben

Bestehenden Tasksequenzschritt in einer Tasksequenz editieren

In diesem Beitrag möchte ich euch zeigen, wie ihr einen Tasksequenzschritt, in einer Tasksequenz über Powershell verändern könnt.

Was ist zu tun?

  1. Bestehende Tasksequenz laden (Get-CMTaskSequence)
  2. IResultObject “TaskSequence” aus dem TaskSequencePackage ziehen
  3. Existierenden Tasksequenzschritt aus der Tasksequenz heraussuchen und Werte ändern.
  4. Speichern der Änderungen

Wenn ihr meinen ersten Beitrag hierzu kennt, kommen euch die Schritte sicher bekannt vor. Wenn nicht, schaut ihn euch ggf. noch einmal an, denn ich werde hier nur auf den Punkt 3. näher eingehen 🙂 Bestehende Tasksequenz über Powershell editieren.

Im Unterschied zum Hinzufügen eines neuen Tasksequence Step, werden wir die bestehenden Tasksequenz zunächst nach dem Schritt durchsuchen, den wir ändern wollen. Read more

Auslesen der Computer Variables per Powershell Script

Sicher seid ihr schon auf die Computer Variables (Eigenschaften eines Gerätes/ Reiter: Variables) gestoßen oder nutzt dieses vielleicht sogar in euren Tasksequenzen. Innerhalb der Tasksequenzen ist der Zugriff auf die Computer Variables analog zur den Tasksequenz Variables: Entweder über den Tasksequenz-Schritt oder schlicht als Umgebungsvariable, innerhalb des “Run Command Line”-Schrittes, in dem die Variable in “%” gesetzt wird.

Doch wie sieht es aus, wenn der Wert ausserhalb der Tasksequenz abgefragt werden soll?

In diesem Artikel möchte ich euch den Weg über Powershell beschreiben. Read more

Bestehende Tasksequenz über Powershell editieren

Angenommen es soll eine (oder mehrere) Tasksequence um einen (oder mehrere) Schritte erweitert werden. Eine Lösung wäre den Auszubildenden endlich wieder eine sinnvolle Aufgabe zu übergeben 😉 Eine andere, das Problem mittels Powershell-Scripting zu lösen.

Ich habe mich für das Scripting entschieden ..

Was ist zu tun?

  1. Bestehende Tasksequenz laden (Get-CMTaskSequence)
  2. IResultObject “TaskSequence” aus dem TaskSequencePackage ziehen
  3. Neuen Tasksequenzschritt “SMS_TaskSequence_*Action” erzeugen
  4. Neuen Tasksequenzschritt in die bestehende Liste aufnehmen
  5. Speichern der Änderungen

Read more

Device Collections, Abfrage des Primary User und Active Directory Gruppe

Will man eine Collection dynamisch füllen, greift man auf eine Abfrageregel (Query Rule) zurück. Dabei werden WQL Abfragen erstellt, mit deren Ergebnis die Collection befüllt wird. Der Datenpool, auf den dabei zurückgegriffen wird, ist entsprechend des Collection Types, auf bestimmte Ressourcen Klassen eingeschränkt. So können bspw. bei einer Device Collection, nur die Daten der “System Resource” und “Unknown Systems” abgefragt werden.

Im Normalfall ist das auch passend, da die Device Collections nur Devices enthalten dürfen und umgekehrt.

Soll jetzt eine Device Collection gefüllt werden bei deren Filterkriterien Daten eines zugeordneten primären Benutzers, wie zum Beispiel die Mitgliedschaft einer Active Directory Gruppe, abgefragt werden, kommt man mit der Abfrage nicht weit. Denn die benötigten “User Resource” oder “User Group Resource” stehen in der Device Collection nicht zur Verfügung.

Wie man dennoch zum Ergebnis kommt, möchte ich in diesem Post erläutern. Read more