In the past I’ve always deployed Windows operating systems by building a reference image in Audit Mode, customizing the default user profile, then sysprepping, and then finally capturing. Because using CopyProfile during sysprep can have some strange side effects, I’ve decided to just script the customizations immediately after applying the image to the disk. I can copy our corporate branded backgrounds and modify the default user profile before even the first reboot. I am also using a custom StartLayout file that I’ve called “LayoutModification.xml”. 3 things need to be in the script root:
- Wallpaper folder (this contains 2 folders called 4k and DefaultRes that contains the corporate-branded images. The 4k folder contains images with the same dimensions as the images located in C:\Windows\Web\4K\Wallpaper\Windows on a Windows 10 machine. The DefaultRes folder contains a single 1920×1200 img0.jpg image)
- Lockscreen folder (This contains a single 1920×1200 img100.jpg image that gets copied to C:\Windows\Web\Screen.)
- LayoutModification.xml file (For this, you will modify an existing Start menu layout and then export it using Export-StartLayout. More info here: https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/customize-start-layout)
By doing things this way, I’ve also decided to not even bother building a reference image at all and instead, I now just load the Windows 10 media into MDT and deploy directly from that. It may not be fully patched at deployment time, but that’s still easy enough to do after the fact. I put the below text into a .ps1 file I call “CustomizeWindowsOffline.ps1”. I then put this into a “Run PowerShell Script” task after “Inject Drivers” in the PostInstall section of my task sequence.
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
<# .NOTES =========================================================================== Created on: 11/12/2019 8:59 AM Created by: Jeff Irvine Filename: CustomizeWindowsOffline.ps1 =========================================================================== .DESCRIPTION Customizes Windows 10 from MDT-PE. #> $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment $OSDisk = "$($tsenv.Value("OSDisk"))" $OSDTargetSystemRoot = "$($tsenv.Value("OSDisk"))" + "\Windows" ########## Rename default wallpaper ########## Write-Host "Renaming default backgrounds..." Rename-Item $OSDTargetSystemRoot\Web\Wallpaper\Windows\img0.jpg img1.jpg -Force Rename-Item $OSDTargetSystemRoot\Web\Screen\img100.jpg img106.jpg -Force ########## Copying new backgrounds ########## Write-Host "Copying new backgrounds..." Copy-Item $PSScriptRoot\Wallpaper\DefaultRes\img0.jpg $OSDTargetSystemRoot\Web\Wallpaper\Windows\img0.jpg Copy-Item $PSScriptRoot\Wallpaper\4k\*.* $OSDTargetSystemRoot\Web\4K\Wallpaper\Windows Copy-Item $PSScriptRoot\Lockscreen\img100.jpg $OSDTargetSystemRoot\Web\Screen ########## Load Default user hive ########## Write-Host "Creating HKU Drive..." New-PSDrive HKU -Root HKEY_Users -PSProvider Registry Write-Host "Loading Default user hive..." REG LOAD HKU\Default $OSDisk\Users\Default\NTUSER.DAT ############ Computer Icon ############## Write-Host "Adding Computer icon to desktop..." #Registry key path $ICpath = "HKU:\Default\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" #Property name $ICname = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" #check if the property exists if (!(Test-Path $ICpath)) { #create a new property New-Item -Path $ICpath -Force | Out-Null New-ItemProperty -Path $ICpath -Name $ICname -Value 0 -PropertyType DWORD -Force | Out-Null } Else { #set property value New-ItemProperty -Path $ICpath -Name $ICname -Value 0 -PropertyType DWORD -Force | Out-Null } ############ Explorer Options ############ Write-Host "Setting Explorer options..." #Registry key path $ExAdvPath = "HKU:\Default\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Write-Host "Unhiding File Extensions..." Set-ItemProperty -Path $ExAdvPath -Name "HideFileExt" -Value 0 Write-Host "Setting Explorer LaunchTo..." Set-ItemProperty -Path $ExAdvPath -Name "LaunchTo" -Value 1 ############ Internet Explorer Options ############ Write-Host "Setting IE Options..." $IEMainPath = "HKU:\Default\Software\Microsoft\Internet Explorer\Main" Write-Host "Setting IE Start Page..." Set-ItemProperty -Path $IEMainPath -Name "Start Page" -Value "https://www.google.com" ############ Search Taskbar Icon ############# Write-Host "Setting Search to an icon..." $SearchBox = "HKU:\Default\Software\Microsoft\Windows\CurrentVersion\Search" Set-ItemProperty -Path $SearchBox -Name "SearchboxTaskbarMode" -Value 1 ############ Cortana Taskbar Icon ############# Write-Host "Setting Cortana icon to hidden..." $CortanaIcon = "HKU:\Default\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Set-ItemProperty -Path $CortanaIcon -Name "ShowCortanaButton" -Value 0 ############ Disable Background compression ########### Write-Host "Disabling background compression..." $BGC = "HKU:\Default\Control Panel\Desktop" New-ItemProperty -Path $BGC -Name "JPEGImportQuality" -Value 100 -PropertyType DWORD | Out-Null Write-Host "Sleeping for 5 seconds..." sleep -Seconds 5 ###### Unload Default user hive ###### Write-Host "Unloading Default user hive..." $unloaded = $false $attempts = 0 while (!$unloaded -and ($attempts -le 5)) { [gc]::Collect() # necessary call to be able to unload registry hive REG UNLOAD HKU\Default $unloaded = $? $attempts += 1 } if (!$unloaded) { Write-Warning "Unable to dismount default user registry hive at HKU\DEFAULT!" } Write-Host "Removing PS Drive..." Remove-PSDrive -Name HKU ############# Setting Custom Start and Taskbar ############# Write-Host "Setting Custom Start and Taskbar..." Copy-Item $PSScriptRoot\LayoutModification.xml $OSDisk\Users\Default\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml -Force Write-Host "`r`n" Write-Host "End of line." |
By using Write-Host, it will output specific text of each operation to it’s own log file that will be created post-task sequence execution.
This script is not perfect but works for me, for now.