När man som jag sätter upp nya SCCM-installationer på löpande band, både ute i verkligheten och i labb/test/demo-miljöer, så blir det snabbt väldigt tradigt att sitta och klicka runt i konsolen för att göra samma saker om och om igen. Tänk om det bara fanns något bra sätt att automatisera saker och ting…
PowerShell to the rescue!
Det mesta, men långt ifrån allt, som kan konfigureras i SCCM går att göra med färdiga cmdlets. En av de lite knepigare sakerna är att skapa task sequences. De färdiga möjligheter vi har innefattar cmdleten New-CMTaskSequence, men den räcker inte för mina och förmodligen de flestas behov. Jag vill normalt integrera MDT med SCCM och använda en MDT-baserad task sequence. Sen finns det ett antal saker som jag alltid gör i mina task sequences, såsom att lägga till diverse variabler, ändra eller ta bort vissa av de inbyggda stegen samt lägga till egna. Vidare finns det saker som jag alltid vill lägga till eller ändra i de standardpaket som används av task sequencen, såsom boot imagen och MDT Settings- och Toolkit-paketen.
Det jag vill uppnå är alltså möjligheten att skapa en bra mall med en task sequence och alla tillhörande paket, som jag enkelt kan återanvända i nya SCCM-miljöer. Använder man bara MDT som fristående verktyg är ju detta väldigt tacksamt eftersom allting man gör bara sparas i en mapp som man kan kopiera om och om igen. Men SCCM är trixigare eftersom task sequencen bl.a. innehåller referenser till paket ID’n i databasen.
Vi kan använda oss av de inbyggda cmdleterna Export-CMTaskSequence och Import-CMTaskSequence (går också att göra i konsolen), men dessa är inte tillräckligt bra och flexibla i min mening. De har haft, och har fortfarande en del buggar, och exporten blir i form av en zip-fil som blir omständig att redigera och uppdatera på ett automatiserat sätt innan en import.
Så istället ska vi titta på hur vi kan göra detta själva med lite knåpande i PowerShell.
Det vi gör i den här guiden är följande:
- Skapa en bra task sequence som vi vill använda som mall och exportera denna. Exportfilen generaliseras sedan så att den går att använda för framtida importer i nya miljöer.
- Importera in de till task sequencen tillhörande paketen till den nya SCCM-miljön.
- Uppdatera export-filen som innehåller task sequencen som ska importeras med korrekta paket ID’n som matchar den nya SCCM-miljön, och importera denna.
I det här exmplet kommer jag använda en helt vanlig MDT-baserad task sequence som innehåller följande paket:
- Boot image
- Windows image
- SCCM klient
- MDT Toolkit paket
- MDT Settings paket
- USMT paketet kommer jag i det här exemplet använda det som är färdigskapat i SCCM
Scripten nedan är alltså ett enkelt exempel, så vill man t.ex. ha fler paket än så här får man lägga till dem i scripten.
Exportera task sequencen
Vi börjar med att manuellt skapa en task sequence i SCCM baserad på MDT (MDT integrationen måste alltså vara gjord) genom att stega igenom wizarden. Vi skapar de paket som behövs, såsom boot imagen och MDT-paketen. Jag har i det här exemplet också skapat ett eget paket för SCCM klienten där jag har lagt med senaste cumulative update. Vi modifierar task sequencen och de tillhörande paketen och lägger till och ändrar allt som vi tycker är bra. När vi känner oss nöjda och har en bra mall som vi vill återanvända så exporterar vi den med följande script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# Specify the site code $SiteCode = "S01" # Specify the name of the task sequence template to be exported, and the name of the export file $TSTemplateName = "Task Sequence Template" $TSTemplateFile = "C:\Task Sequence Template\TStemplate.xml" # Specify the names of the images and packages used in the task sequence $WindowImageName = "Windows 8.1 Enterprise x64" $SCCMClientPackageName = "SCCM Client With Hotfixes" $USMTPackageName = "User State Migration Tool for Windows 8" $MDTToolkitName = "MDT 2013 Toolkit Package" $MDTSettingsPackageName = "MDT 2013 Settings Package For Windows 8.1 x64" # Import the ConfigMgr module and set location Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) Set-Location ($SiteCode + ":") # Export task sequence (Get-CMTaskSequence | Where-Object {$_.Name -eq $TSTemplateName}).Sequence | Out-File $TSTemplateFile # Get the Package IDs for the packages used in the task sequence $TSReferenceWindowsImage = (Get-CMOperatingSystemImage | Where-Object {$_.Name -eq $WindowImageName}).PackageID $TSReferenceClientPackage = (Get-CMPackage | Where-Object {$_.Name -eq $SCCMClientPackageName}).PackageID $TSReferenceUSMT = (Get-CMPackage | Where-Object {$_.Name -eq $USMTPackageName}).PackageID $TSReferenceMDTToolkit = (Get-CMPackage | Where-Object {$_.Name -eq $MDTToolkitName}).PackageID $TSReferenceMDTSettings = (Get-CMPackage | Where-Object {$_.Name -eq $MDTSettingsPackageName}).PackageID # Function to replace strings in a file Function Replace-StringInFile([string]$FileName,[string]$TextToReplace,[string]$NewText) { (Get-Content $FileName) | Foreach-Object {$_ -replace $TextToReplace, $NewText} | Set-Content $FileName -Encoding Unicode } # Replace all package ID's to some unique string that we can easily identify when importing the task sequence Replace-StringInFile $TSTemplateFile $TSReferenceWindowsImage "UNIQUE_WINDOWS_IMAGE_ID" Replace-StringInFile $TSTemplateFile $TSReferenceClientPackage "UNIQUE_CLIENT_PACKAGE_ID" Replace-StringInFile $TSTemplateFile $TSReferenceUSMT "UNIQUE_USMT_PACKAGE_ID" Replace-StringInFile $TSTemplateFile $TSReferenceMDTToolkit "UNIQUE_MDT_TOOLKIT_PACKAGE_ID" Replace-StringInFile $TSTemplateFile $TSReferenceMDTSettings "UNIQUE_MDT_SETTINGS_PACKAGE_ID" |
Vi använder oss här alltså inte av Export-CMTaskSequence. Istället hämtar vi värdet från attributet Sequence från Get-CMTaskSequence, vilket innehåller just hela task sequencen i xml-format.
Uppdatera variablerna i början så att site code, namn på task sequencen, namn och sökväg till exportfilen samt namnen på paketen i task sequencen matchar din miljö.
Efter att scriptet körts har vi fått en xml-fil som innehåller hela task sequencen. Alla paket ID’n har bytts ut mot unika påhittade strängar, som vi enkelt kan hitta och byta ut igen när task sequencen ska importeras till en ny miljö. Den här filen sparar vi tillsammans med alla paket som används i task sequencen, så att vi har en liten mapp som innehåller allt som vi vill återanvända.
Importera paketen
I vår nya miljö där vi vill återanvända vår task sequence med tillhörande paket så börjar vi med att importera in paketen med följande script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# Specify the site code $SiteCode = "S01" # Specify distribution point group $DistributionPointGroup = "All DPs" # Specify package names and source paths $BootImageName = "MDT Boot Image x64" $BootImagePath = "\\sccmrap\sources\OSD\Boot Images\WinPE 5.0\x64\winpe.wim" $WindowsImageName = "Windows 8.1 Enterprise x64" $WindowsImagePath = "\\sccmrap\sources\OSD\OS Images\Win8.1x64-20141015.wim" $MDTToolkitPackageName = "MDT 2013 Toolkit Package" $MDTToolkiTPackagePath = "\\sccmrap\sources\OSD\MDT 2013 Toolkit Package" $MDTSettingsPackageName = "MDT 2013 Settings Package For Windows 8.1 x64" $MDTSettingsPackagePath = "\\sccmrap\sources\OSD\MDT 2013 Settings Packages\Windows 8.1\x64" $SCCMClientPackageName = "SCCM Client With Hotfixes" $SCCMClientPackagePath = "\\sccmrap\Sources\Applications\SCCM Client With Hotfixes" # Import the ConfigMgr module and set location Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) Set-Location ($SiteCode + ":") # Import the boot image New-CMBootImage -Name $BootImageName -Path $BootImagePath -Index 1 # Enable command support in the boot image $BootImageWMIObject = Get-WmiObject -Namespace "Root\SMS\Site_$SiteCode" -Class SMS_BootImagePackage -Filter "Name='$BootImageName'" $BootImageWMIObject.Get() $BootImageWMIObject.EnableLabShell = 'True' $BootImageWMIObject.Put() # Deploy the boot image from PXE-enabled distribution points $BootImageWMIObject.Get() $BootImageWMIObject.PkgFlags = '1024' $BootImageWMIObject.Put() # Import the operating system image New-CMOperatingSystemImage -Name $WindowsImageName -Path $WindowsImagePath # Import the MDT toolkit package New-CMPackage -Name $MDTToolkitPackageName -Path $MDTToolkitPackagePath # Import the MDT settings package New-CMPackage -Name $MDTSettingsPackageName -Path $MDTSettingsPackagePath # Import the SCCM client package New-CMPackage -Name $SCCMClientPackageName -Path $SCCMClientPackagePath # Distribute the packages to the distribution point group Start-CMContentDistribution -BootImageName $BootImageName -DistributionPointGroupName $DistributionPointGroup Start-CMContentDistribution -OperatingSystemImageName $WindowsImageName -DistributionPointGroupName $DistributionPointGroup Start-CMContentDistribution -PackageName $MDTToolkitPackageName -DistributionPointGroupName $DistributionPointGroup Start-CMContentDistribution -PackageName $MDTSettingsPackageName -DistributionPointGroupName $DistributionPointGroup Start-CMContentDistribution -PackageName $SCCMClientPackageName -DistributionPointGroupName $DistributionPointGroup |
Ändra site code, namn på distributionspunktsgrupp samt namn och sökvägar till paketen så att de matchar din miljö.
Scriptet kommer skapa Windows image, boot image samt de övriga paketen som Packages. Boot imagen kommer konfigureras med flaggan för att det ska disttribueras från PXE, samt aktivera stöd för kommandoprompt med F8.
Till sist kommer samtliga paket att distribueras till den distributionspunktsgrupp som vi angett (jag skapar ALLTID en grupp även om det bara finns en enda DP).
Importera task sequencen
När nu alla paket finns på plats kan vi importera in vår sparade task sequence med följande script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# Specify the site code $SiteCode = "S01" # Specify the name of the task sequence template file that will be imported $TSTemplateFile = "C:\Task Sequence Template\TStemplate.xml" # Specify the name of the new task sequence that will be created $TSName = "Install Windows 8.1 x64" # Specify the names of the images and packages used in the task sequence $BootImageName = "MDT Boot Image x64" $WindowImageName = "Windows 8.1 Enterprise x64" $SCCMClientPackageName = "SCCM Client With Hotfixes" $USMTPackageName = "User State Migration Tool for Windows 8" $MDTToolkitName = "MDT 2013 Toolkit Package" $MDTSettingsPackageName = "MDT 2013 Settings Package For Windows 8.1 x64" # Name of the unique strings in the task sequence template file that represent the package ID's $TSReferenceWindowsImage = "UNIQUE_WINDOWS_IMAGE_ID" $TSReferenceClientPackage = "UNIQUE_CLIENT_PACKAGE_ID" $TSReferenceUSMT = "UNIQUE_USMT_PACKAGE_ID" $TSReferenceMDTToolkit = "UNIQUE_MDT_TOOLKIT_PACKAGE_ID" $TSReferenceMDTSettings = "UNIQUE_MDT_SETTINGS_PACKAGE_ID" # Import the ConfigMgr module and set location Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) Set-Location ($SiteCode + ":") # Get the Package IDs for the packages used in the task sequence $TSReferenceBootImage = (Get-CMBootImage | Where-Object {$_.Name -eq $BootImageName}).PackageID $TSReferenceWindowsImageNEW = (Get-CMOperatingSystemImage | Where-Object {$_.Name -eq $WindowImageName}).PackageID $TSReferenceClientPackageNEW = (Get-CMPackage | Where-Object {$_.Name -eq $SCCMClientPackageName}).PackageID $TSReferenceUSMTNEW = (Get-CMPackage | Where-Object {$_.Name -eq $USMTPackageName}).PackageID $TSReferenceMDTToolkitNEW = (Get-CMPackage | Where-Object {$_.Name -eq $MDTToolkitName}).PackageID $TSReferenceMDTSettingsNEW = (Get-CMPackage | Where-Object {$_.Name -eq $MDTSettingsPackageName}).PackageID # Function to replace strings in a file Function Replace-StringInFile([string]$FileName,[string]$TextToReplace,[string]$NewText) { (Get-Content $FileName) | Foreach-Object {$_ -replace $TextToReplace, $NewText} | Set-Content $FileName -Encoding Unicode } # Copy the task sequence template file to a new file that we will use for import, so that we don't destroy the original $TSTemplateImportFile = $TSTemplateFile.Substring(0,$TSTemplateFile.Length-4) + "-IMPORTFILE.xml" Copy-Item $TSTemplateFile $TSTemplateImportFile -Force # Replace all package ID's in the task sequence template file with the actual ID's of the packages that will be used Replace-StringInFile $TSTemplateImportFile $TSReferenceWindowsImage $TSReferenceWindowsImageNEW Replace-StringInFile $TSTemplateImportFile $TSReferenceClientPackage $TSReferenceClientPackageNEW Replace-StringInFile $TSTemplateImportFile $TSReferenceUSMT $TSReferenceUSMTNEW Replace-StringInFile $TSTemplateImportFile $TSReferenceMDTToolkit $TSReferenceMDTToolkitNEW Replace-StringInFile $TSTemplateImportFile $TSReferenceMDTSettings $TSReferenceMDTSettingsNEW # Import the task sequence $WMIClass = "SMS_TaskSequencePackage" $TS = [wmiclass]"\\.\root\sms\site_$($SiteCode):$($WMIClass)" $Instance = $TS.CreateInstance() $TSFileContent = Get-Content $TSTemplateImportFile $NewSequence = $TS.ImportSequence($TSFileContent).TaskSequence $Instance.Name = $TSName $NewTSPackageID = $TS.SetSequence($Instance, $NewSequence).SavedTaskSequencePackagePath # Assign a boot image to the task sequence $ImportedTaskSequence = Get-CMTaskSequence -Name $TSName Set-CMTaskSequence -TaskSequence $ImportedTaskSequence -BootImageId $TSReferenceBootImage -UseBootImage $True -UseDefaultText $True |
Ändra site code, namn på exportfilen och den task sequence som ska skapas, samt namnen på paketen i task sequencen så att de matchar din miljö.
Scriptet kommer göra en kopia av exportfilen, så att vi inte förstör orginalet, och uppdatera denna med de riktiga paket ID’n som vi nu har i vår nya miljö. Därefter kommer en ny task sequence att skapas, med det namn som vi har valt, baserad på denna exportfil. Till sist kommer vår boot-image att associeras med task sequencen.
Vóila! Nu har vi en fullt fungerande task sequence, med korrekta paket-referenser, som är redo att börja användas direkt. Inte ett enda klick har vi behövt göra i konsolen.
Ladda ned scripten här