SCCM/SMS & PowerShell: Introduction (2/3)

juin 6, 2011
Pour cette seconde partie, je vais vous proposer un script permettant de déplacer les collections entre sous collections.
La console SCCM ne nous permet pas de réaliser ce type d’opération, voilà pourquoi ce script peut être des plus intéressants.

A. Petit rappel concernant les collections

En SCCM, la notion de collection est très importante, Elle vous permet de grouper des ressources ensembles suivant un ensemble de critères communs.

Via la console, il est possible de lier une collection comme étant enfant d’une autre. Je dis bien lié car une collection reste un objet “neutre” possédant un ensemble de pointeurs hiérarchique indiquant le lien de parenté.

B. Les sous-collections

Prenons l’exemple suivant:

  • Je crée une collection Ma_Collection_1. Par défaut elle sera placée en dessous du noeud portant le nom de Collections qui est le noeud parent le plus élevé. Son nom interne est COLROOT.
  • Je crée ensuite une seconde collection Ma_Collection_2 également sous le noeud Collections.

SCCM-Collection4

  • Je décide ensuite de rendre Ma_Collection_2 enfant de Ma_Collection_1, Je le fait en cliquant sur Ma_Collection_1 –> New –> Link To Collection et je choisis Ma_Collection_2.

SCCM-Collection5

SCCM-Collection6

SCCM-Collection7

Vous constatez que Ma_Collection_2 est maintenant une sous-collection de Ma_Collection_1 mais reste également une sous-collection de Collections.

Ce petit exemple tente à délontrer qu’une collection peut avoir plusieurs liens hiérarchiques sans modifier l’objet en lui-même.

A partit de cet exemple, on peut en déduire qu’un objet Collection contient un ensemble d’objets SubCollection. C’est presque ca Smile En réalité, un lien de parenté entre collections se fait par la création d’un objet SMS_CollectToSubCollect.

Cet objet possède les propriétés suivantes;

  • parentCollectionID
  • subCollectionID

Il suffit de donner l’ID de la collection parent à la première méthode et de donner l’ID de la collection enfant à la seconde méthode.

C. En Powershell, cela donne ceci

Voici la fonction qui permet de créer une relation entre 2 collections via l’utilisation de l’objet SMS_CollectToSubCollect:

Function ImportCollections($collData, $parentCollID) {
foreach ($elem in $collData){
$elemID = $elem.CollectionID
$oSubColl = $conSCCM.CreateInstance("SMS_CollectToSubCollect")
$oSubColl["parentCollectionID"].StringValue = $parentCollID
$oSubColl["subCollectionID"].StringValue = $elemID
$oSubColl.Put()
Write-Host "Collection $elemID imported into $parentCollID"
}
Write-Host "SubCollections imported into Parent Collection: " $collData.Length "item(s)" -ForegroundColor Green
}

Vu que le but du programme est de déplacer une collection et non de multiplier ses liens hiérarchiques, voici la fonction que j’utilise pour supprimer le lien précédent:

Function DeleteObsoleteCollections($collData,[string]$oSc, [String]$oldPColl){
$smsSiteCode = "root\SMS\Site_" + $oSc
foreach ($elem in $collData){
$elemID = $elem.CollectionID
$subCollObs = Get-WmiObject -namespace $smsSiteCode -query "select * from SMS_CollectToSubCollect where parentCollectionID = '$oldPColl' and subCollectionID = '$elemID'"
$subCollObs.Delete()
Write-Host "Collection $elemID deleted from $oldPColl"
}
Write-Host "Subcollection deleted from Parent Collection: " $collData.Length "item(s)" -ForegroundColor Green
}

Voici le programme complet. Il a pour but de permettre un déplacement de dépendance hiérarchique entre collections.

Son fonctionnement est relativement simple, je réalise un export des collections dans un fichier csv.

Je traite le fichier manuellement pour seul les collections désirées soient traitées.

Je réimporte ensuite le fichier avec le nom de la collection parent qui servira de point hiérarchique aux collections enfants se trouvant dans le fichier.

E. Exemple complet

#=========================================================================
#
#NAME: PS-SCCMCollToSubColl
#
#VERSION: 1.0
#AUTHOR: Malfroidt Olivier
#DATE: 20/05/2011
#
#COMMENT:
#
#=========================================================================

#*****************
#Arguments
#*****************
param ([string]$mode, [string]$file, [string]$sccmSrv, [string]$siteCode, [String]$parentColl, [String]$oldParentColl)

#*****************
#Assemblies
#*****************
[System.Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\Microsoft Configuration Manager\AdminUI\bin\adminui.wqlqueryengine.dll")
[System.Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\Microsoft Configuration Manager\AdminUI\bin\microsoft.configurationmanagement.managementprovider.dll")

#*****************
#Variables
#*****************
$conSCCM = $null
$importedQueries = @()

#*****************
#Functions
#*****************

#*************
#HelpMessage
#*************

Function HelpMsg()
{
$helpText=@"

Name: PS-SCCMCollToSubColl - v1.0 Release

Usage:
PS-SCCMCollToSubColl -mode [IMPORT | EXPORT] -file [filename] [-sccmSrv [server name] -siteCode [SCCM site code] -parentColl [Parent Collection] -oldParentColl [Old Parent Collection]]

Options:
Mandatory
-mode [IMPORT | EXPORT]: Specify if you want import Collections to SCCM or export data from SMS
-file [Filename]: Desination file if you export data and Source file if you import data.
-sccmSrv [ServerName]: In case of Export mode, you must specify the SCCM Server name.
-siteCode [SMS Site code]: In case of Export mode, you must specify the SCCM Site code.
-parentColl [SCCM Parent Colllection]: New Parent Collection ID
-oldParentColl [Old Parent Collection]: Old Parent Collection ID
Exemples:
Export:
PS-SCCMCollToSubColl -mode EXPORT -file "
D:\Temp\Export.csv" -sccmSrv SERVERNAME -siteCode "00A"
Import:
PS-SCCMCollToSubColl -mode IMPORT -file "
D:\Temp\Export.csv" -sccmSrv SERVERNAME -siteCode "00A" -parentColl "00A0000D" -oldParentColl "COLLROOT"
"
@
$helpText
exit
}

Function ConnectionSCCM(){
$nameValues = New-Object -TypeName microsoft.configurationmanagement.managementprovider.SmsNamedValuesDictionary
$script:conSCCM = New-Object -TypeName microsoft.configurationmanagement.managementprovider.WqlQueryEngine.WqlConnectionManager -ArgumentList $nameValues
$script:conSCCM.Connect([system.Net.dns]::GetHostName().ToUpper())
}

Function CloseConnSCCM(){
$script:conSCCM.Close()
}

Function ImportCollections($collData, $parentCollID) {
foreach ($elem in $collData){
$elemID = $elem.CollectionID
$oSubColl = $conSCCM.CreateInstance("SMS_CollectToSubCollect")
$oSubColl["parentCollectionID"].StringValue = $parentCollID
$oSubColl["subCollectionID"].StringValue = $elemID
$oSubColl.Put()
Write-Host "Collection $elemID imported into $parentCollID"
}
Write-Host "SubCollections imported into Parent Collection: " $collData.Length "item(s)" -ForegroundColor Green
}

Function DeleteObsoleteCollections($collData,[string]$oSc, [String]$oldPColl){
$smsSiteCode = "root\SMS\Site_" + $oSc
foreach ($elem in $collData){
$elemID = $elem.CollectionID
$subCollObs = Get-WmiObject -namespace $smsSiteCode -query "select * from SMS_CollectToSubCollect where parentCollectionID = '$oldPColl' and subCollectionID = '$elemID'"
$subCollObs.Delete()
Write-Host "Collection $elemID deleted from $oldPColl"
}
Write-Host "Subcollection deleted from Parent Collection: " $collData.Length "item(s)" -ForegroundColor Green
}

Function ExportCollections ([string]$oSrv, [string]$oSc, [string]$oFile) {
$smsSiteCode = "root\SMS\Site_" + $oSc
$oCollSccm = Get-WmiObject -ComputerName $oSrv -Namespace $smsSiteCode -Query "select * from SMS_Collection"
$oCollSccm | select-object Name, CollectionID | Export-Csv $oFile -Delimiter ";"
write-host "Collections exported from SCCM: " $oCollSccm.Length "item(s)"
}

#*****************
#Main
#*****************

try{
if (($mode -ne "") -and ($file -ne "")) {
switch ($mode.ToUpper()){
"IMPORT" {
if ($parentColl -ne ""){
Write-Host "SubCollections move into SCCM: Job start" -ForegroundColor Blue
$importedCollection = import-csv $file -Delimiter ";"
ConnectionSCCM
ImportCollections $importedCollection  $parentColl
DeleteObsoleteCollections $importedCollection $siteCode $oldParentColl
CloseConnSCCM
Write-Host "SubCollections move into SCCM: Job done" -ForegroundColor Blue
}Else{
Write-Host "IMPORT ERROR: Incorrect arguments provided" -ForegroundColor Red
HelpMsg
}
}
"EXPORT" {
if (($sccmSrv -ne "") -and ($siteCode -ne "")) {
Write-Host "Collections export from SCCM: Job start" -ForegroundColor Blue
ExportCollections $sccmSrv  $siteCode $file
Write-Host "Collections export from SCCM: Job done" -ForegroundColor Blue
} else {
Write-Host "EXPORT ERROR: Incorrect arguments provided" -ForegroundColor Red
HelpMsg
}
}
Default {
HelpMsg
}
}
}else{
Write-Host "GENERAL ERROR: Incorrect arguments provided" -ForegroundColor Red
HelpMsg
}
}catch {
Write-Host -ForegroundColor Red "CRITICAL ERROR: " $Error[0]
}

Source: http://msdn.microsoft.com/en-us/library/cc143948.aspx

Enjoy !!!

It's only fair to share...Share on Facebook

Leave a Reply