This blog is owned and operated by the ANZ ConfigMgr Premier Field Engineer team.
Contributors
Ian BartlettMatt ShadboltGeorge Smpyrakis
I’m on a scripting rampage at the moment writing tools for the common things I do for each customer. Here’s my latest script.
This powershell script will:
- Check for prereqs (WAIK, DISM) - Builds the WinPE dev environment (in either x86 or x64) - Mounts the WIM - Prompts to install non-default WinPE packages (HTA or Script Host support, for example) - Adds Trace32.exe to the image - Prompts asking if you want to add any other files to the image - Unmounts and saves the custom image ready for SCCM or MDT.
################################################################################################ ########## Created by Matt Shadbolt ########## ################################################################################################ # Global Variables $HTA = 'winpe-hta.cab' $LEGACY = 'winpe-legacysetup.cab' $MDAC = 'winpe-mdac.cab' $PPPOE = 'winpe-pppoe.cab' $SCRIPTING = 'winpe-scripting.cab' $CLIENT = 'winpe-setup-client.cab' $SERVER = 'winpe-setup-server.cab' $SETUP = 'winpe-setup.cab' $WDS = 'winpe-wds-tools.cab' $WMI = 'winpe-wmi.cab'
$LongHTA = 'HTML Application Support' $LongLEGACY = 'The Media Setup features' $LongMDAC = 'Microsoft Data Access Components' $LongPPPOE = 'PPOE services' $LongSCRIPTING = 'Windows Script Host support' $LongCLIENT = 'the Client Setup features' $LongSERVER = 'the Server Setup features' $LongSETUP = 'the Setup features' $LongWDS = 'WDS tools' $LongWMI = 'WMI support'
$RequiredCopyCmd = Test-Path "C:\Program Files\Windows AIK\Tools\PETools\copype.cmd" $RequiredWinPackages = Test-Path "C:\Program Files\Windows AIK\Tools\PETools\x86\WinPE_FPs\$HTA" $RequiredDism = Test-Path "C:\Windows\System32\dism.exe" $RequiredTrace32 = Test-Path "C:\Program Files\ConfigMgr 2007 Toolkit\CCM Tools\Trace32.exe"
# Start Script Write-Host "#########################################################" -foregroundcolor yellow Write-Host "Welcome to my WinPE Customization Script! Enjoy your stay." -foregroundcolor yellow Write-Host "#########################################################" -foregroundcolor yellow
# Check requirements
If ($RequiredCopyCmd -eq $False) { Write-Host "copype.cmd could not be found. Script Exiting!" -foregroundcolor yellow exit } Else {} If ($RequiredWinPackages -eq $False) { Write-Host "WinPE Packages not be found. This may not run!" -foregroundcolor yellow } Else {} If ($RequiredDism -eq $False) { Write-Host "Dism couple not be found. Script Exiting!" -foregroundcolor yellow exit } Else {} If ($RequiredTrace32 -eq $False) { Write-Host "Trace32 couple not be found. This may not run!" -foregroundcolor yellow } Else {}
Start-Sleep -s 3 Write-Host "" $Arch = Read-Host "Would you like x86 or x64?"
If ($Arch -eq 'x64') { $PackagePath = "amd64" } Else { $PackagePath = "x86" } Write-Host "" Write-Host "I'm just creating your WinPE dev environment (C:\Winpe_$Arch)" -foregroundcolor yellow Write-Host "" Start-Sleep -s 3
If ($Arch -eq "x64") { CD "C:\Program Files\Windows AIK\Tools\PETools" .\copype.cmd amd64 C:\winpe_$Arch Write-Host "$Arch dev environment created" -foregroundcolor yellow } ElseIf ($Arch -eq "x86") { CD "C:\Program Files\Windows AIK\Tools\PETools" .\copype.cmd x86 C:\winpe_$Arch Write-Host "$Arch dev environment created" -foregroundcolor yellow } Else { Write-Host "$Arch does not match either x86 or x64. Please start this script again" -foregroundcolor yellow exit } Start-Sleep -s 3 Write-Host "" Write-Host "Just going to mount your WIM" -foregroundcolor yellow Dism /Mount-Wim /WimFile:C:\winpe_$Arch\winpe.wim /index:1 /MountDir:C:\winpe_$Arch\mount Write-Host "" Write-Host "Mounted" -foregroundcolor yellow Write-Host "" Start-Sleep -s 3 Write-Host "Now we will customize the boot image" -foregroundcolor yellow Write-Host ""
$HTAeqYES = Read-Host "Would you like to install $HTA which enables $LongHTA? Y/N" $LEGACYeqYES = Read-Host "Would you like to install $LEGACY which enables $LongLEGACY? Y/N" $MDACeqYES = Read-Host "Would you like to install $MDAC which enables $LongMDAC? Y/N" $PPPOEeqYES = Read-Host "Would you like to install $PPPOE which enables $LongPPPOE? Y/N" $SCRIPTINGeqYES = Read-Host "Would you like to install $SCRIPTING which enables $LongSCRIPTING? Y/N" $CLIENTeqYES = Read-Host "Would you like to install $CLIENT which enables $LongCLIENT? Y/N" $SERVEReqYES = Read-Host "Would you like to install $SERVER which enables $LongSERVER? Y/N" $SETUPeqYES = Read-Host "Would you like to install $SETUP which enables $LongSETUP? Y/N" $WDSeqYES = Read-Host "Would you like to install $WDS which enables $LongWDS? Y/N" $WMIeqYES = Read-Host "Would you like to install $WMI which enables $LongWMI? Y/N"
If ($HTAeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$HTA" } Else {} If ($LEGACYeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$LEGACY" } Else {} If ($MDACeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$MDAC" } Else {} If ($PPPOEeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$PPPOE" } Else {} If ($SCRIPTINGeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$SCRIPTING" } Else {} If ($CLIENTeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$CLIENT" } Else {} If ($SERVEReqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$SERVER" } Else {} If ($SETUPeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$SETUP" } Else {} If ($WDSeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$WDS" } Else {} If ($WMIeqYES -eq 'Y') { dism /image:C:\winpe_$Arch\mount /Add-Package:"C:\Program Files\Windows AIK\Tools\PETools\$PackagePath\WinPE_FPs\$WMI" } Else {}
Start-Sleep -s 3
Write-Host "Windows Package installation complete" -foregroundcolor yellow Write-Host "" Start-Sleep -s 3
$Trace32eqYES = Read-Host "Would you like to also add Trace32 to the boot image? Y/N"
If ($Trace32eqYES -eq 'Y') { copy "C:\Program Files\ConfigMgr 2007 Toolkit\CCM Tools\Trace32.exe" C:\winpe_$Arch\mount } Else {}
MKDIR C:\winpe_$Arch\mount\CustomFiles $MorePackage = Read-Host "Are there any other files you want to install? Y/N"
While ($MorePackage -eq 'Y') { $FilePath = Read-Host "Please enter source file path (no quotation marks please)" Write-Host "" copy $FilePath C:\winpe_$Arch\mount\CustomFiles $MorePackage = Read-Host "Are there any other files you want to install? Y/N" }
Write-Host "" Write-Host "Custom Package installation complete" -foregroundcolor yellow Write-Host "" Write-Host "Now we'll clean up and save your custom WIM" -foregroundcolor yellow Write-Host ""
dism /Unmount-Wim /MountDir:C:\winpe_$Arch\mount /Commit copy c:\winpe_$Arch\winpe.wim c:\winpe_$Arch\ISO\sources\CustomWIM_Arch.wim dism /Unmount-Wim /MountDir:C:\winpe_$Arch\mount /Discard dism /Cleanup-Wim
Write-Host "" Write-Host "" Write-Host "Complete!" -foregroundcolor yellow Write-Host "" Write-Host "" Write-Host "" Write-Host "Your custom WinPE WIM can be found c:\winpe_$Arch\ISO\sources\CustomWIM_Arch.wim" -foregroundcolor Red -backgroundcolor yellow
Matt Shadbolt
I’ve been working hard lately on the various USMT migration scenarios using SCCM with hardlinking and State Migration Points. One of the frustrating things during this process is creating ‘user state’. Creating user state for your test migrations is important as you need to ensure that your testing covers the regular places that users will store files, and that USMT is doing it’s job and migrating this data.
The frustrating part is the time it takes to create some reasonable user state. You want to add files and folders to users profiles across multiple locations. I’ve written a VB Script to automate this process. The script will work for either Windows XP or Windows 7 environments. It basically creates a bunch of files and folders in the logged in users Desktop, My Documents, My Pictures and App Data directories.
'' USMT Environment Setup '''' Created by Matt Shadbolt ''Option Explicit'Declare VariablesDim objFSO, objFolder, strDirectoryDim objNetworkDim profilePathDim xDim filetxt, getname, pathDim LocalAppDataPath, RoamingAppDataPathDim MyDocuments, MyDesktop, MyPictures'Set Variablesx = 0Set objFSO = CreateObject("Scripting.FileSystemObject")Set objNetwork = CreateObject("WScript.Network")profilePath = UserInput( "Is this for XP or WIN7?")' Check if XP or Windows 7If profilePath = "XP" ThenprofilePath = "C:\Documents and Settings\"LocalAppDataPath = "\Local Settings\Application Data\"RoamingAppDataPath = "\Application Data\"MyDocuments = "My Documents"MyDesktop = "Desktop"MyPictures = "My Documents\My Pictures"ElseIf profilePath = "WIN7" ThenprofilePath = "C:\Users\"LocalAppDataPath = "\AppData\Local\"RoamingAppDataPath = "\AppData\Roaming\"MyDocuments = "Documents"MyDesktop = "Desktop"MyPictures = "Pictures"ElseMsgBox "You need to enter either XP or WIN7 (CaSe SeNsItIvE) "Wscript.QuitEnd If' Desktop FoldersWhile x < 10 strDirectory = profilePath & objNetwork.Username & "\" & MyDesktop & "\DesktopFolder" & x Set objFolder = objFSO.CreateFolder(strDirectory) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "TextFile" & x & ".txt", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "Shortcut" & x & ".lnk", True) x = x + 1Wendx = 0' My DocumentsWhile x < 10 strDirectory = profilePath & objNetwork.Username & "\" & MyDocuments & "\DocumentsFolder" & x Set objFolder = objFSO.CreateFolder(strDirectory) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc1" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc2" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc3" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc4" & x & ".doc", True) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "WordDoc5" & x & ".doc", True) x = x + 1Wendx = 0' My PicturesWhile x < 10 strDirectory = profilePath & objNetwork.Username & "\" & MyPictures & "\PicturesFolder" & x Set objFolder = objFSO.CreateFolder(strDirectory) Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "Picture" & x & ".jpg", True) x = x + 1Wendx = 0' AppDatat\LocalstrDirectory = profilePath & objNetwork.Username & LocalAppDataPath & "SomeAppData"Set objFolder = objFSO.CreateFolder(strDirectory)While x < 10 Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "AppDataFile" & x & ".appData", True) x = x + 1Wendx = 0' AppData\RoamingstrDirectory = profilePath & objNetwork.Username & RoamingAppDataPath & "SomeAppData"Set objFolder = objFSO.CreateFolder(strDirectory)While x < 10 Set filetxt = objFSO.CreateTextFile(strDirectory &"\" & "AppDataFile" & x & ".appData", True) x = x + 1Wendx = 0MsgBox "Success!"''' Functions ''''Input OS typeFunction UserInput( myPrompt ) If UCase( Right( WScript.FullName, 12 ) ) = "\CSCRIPT.EXE" Then WScript.StdOut.Write myPrompt & " " UserInput = WScript.StdIn.ReadLine Else UserInput = InputBox( myPrompt ) End IfEnd Function