This is an old revision of the document!
Table of Contents
Building a Custom Windows Reference Image
Why Custom?
I've never been a fan of the vanilla out-of-box experience in Windows. Consequently, regardless of the deployment tools, I've always felt it necessary to build a custom reference image. Following is a breakdown of my perspective on Vanilla vs Custom images.
Vanilla Pros
- Ready to deploy without any extra time and effort required.
- Consistent out-of-box user experience across all deployments.
Vanilla Cons
- Will be out of date on patches just months after release.
- Deployment times will lengthen as the build requires more and more post-imaging patches.
- Likelihood of unwanted applications being included, especially with the advent of the Windows Store.
- Deployment times will lengthen if cleanup is necessary, especially if it cannot be automated to reliably produce consistent results.
- Lack of desired 3rd party application integration.
- Deployment times will lengthen due to post-imaging application deployment, scripted or manual.
- Default user profile experience begs to be customized.
- If the default user profile experience needs to be customized for many users, it will have to be done post-deployment, and per profile. While some things may be easy to automate, some will have to be done by hand. Ultimately, this will cause deployment times to lengthen.
Custom Pros
- Depending on image update frequency, likely to not be very far behind on patches.
- Unwanted applications can be completely cleaned out.
- Must-have applications and utilities can be integrated in to the image.
- Default user profile can include many adjusted settings, including for 3rd party applications.
- Deployment times reduced by integrating as many common post-imaging necessities as possible.
- Consistent out-of-box user experience across all deployments.
Custom Cons
- Extra time and effort spent on maintaining the image and re-capturing it for deployment.
- Customizing the default user profile occasionally introduces issues that must be troubleshooted, further increasing image maintenance times.
Trade-off Summary
Ultimately, the goal is to always deliver a consistent out-of-box user experience across all deployments. Going with the custom image means front-loading time and effort on customizing, to save huge amounts of time on deployments in the long run.
Overview
Here is a brief overview of the process.
- Create a VM to host the reference build, perform vanilla Windows setup from an ISO, and get in to Audit Mode.
- Perform a variety of configuration changes, cleanup, software/utility additions, and Windows Updates to establish a desirable baseline.
- Take snapshots at critical points throughout the process for convenient roll-back.
- Sysprep and capture the disk image.
Software Used
- Hyper-V - My virtualization environment of choice as it is freely available on Windows.
- Windows ADK - Requisite for WDS/MDT, but also a required toolkit to prepare a WinPE boot environment.
The Build (Windows 10 1909.4)
This document is currently a work in progress as it is being updated for my approach to deploying build 1909.4.
Creating a New Virtual Machine in Hyper-V
New → Virtual Machine
- Specify Name and Location
- Example name pattern
Windows10_Reference
- Specify Generation
- Select
Generation 2
for 64bit UEFI operating systems, otherwise stick toGeneration 1
- Assign Memory
- Startup Memory
2048
[x] Use Dynamic Memory
- Configure Networking
- Connection
Not Connected
- Connect Virtual Hard Disk
- Leave
(x) Create a virtual hard disk
selected with defaults, should be creating a127 GB
disk.
- Installation Options
- Select
Install an operating system later
Finish
Right-Click → Settings
on the new VM- Processor
- Number of virtual processors
2
- Firmware
- Boot order, set it to
Network, HDD
- Integration Services
- Enable all
- Checkpoints
- Set Checkpoint Type to
Standard checkpoints
- Set Checkpoint File Location to a dedicated path if using non-default.
- Ex:
D:\_hyperv\_checkpoints
- Smart Paging File Location
- Set Smart Paging file location to a dedicated path if using non-default.
- Ex:
D:\_hyperv\_paging
- Close VM Settings
- Create a Checkpoint, rename to
Fresh VM - 2GB dynamic RAM, 2 Cores
Initial Windows 10 Deployment
- We don't always need the DVD drive, so it's not part of the baseline setup, but we need it for initial OS deployment.
Right-Click → Settings
on the new VM- SCSI Controller
DVD Drive → Add → Apply
- Firmware
- Boot order, set it to
DVD Drive, Network, HDD
andOK
Right-Click → Connect
on the VM to connect to its consoleMedia → DVD Drive → Insert Disk…
and mount the appropriate Windows ISOStart
the VM, don't miss thePress any key…
prompt or you'll miss setup and need to restart the VM- Windows Setup
Next → Install now
- If prompted, select the appropriate operating system edition you want to install, ex:
Windows 10 Enterprise
[x] I accept the license terms
andNext
- Select
Custom: Install Windows only (advanced)
- Should see
Drive 0 Unallocated Space 127 GB
soNext
- We need to intercept the setup before it logs in via Administrator, so we can modify the Default user ntuser.dat and prevent OneDrive from installing.
- When setup gets to
Windows needs to restart to continue
force shutdown the VM. - Create a Checkpoint, rename to
Windows Setup, first reboot
- Eject the OS install media and insert WinPE media instead.
- Push
DVD Drive
to the top of the boot order again. - Boot to the WinPE media and create a Checkpoint, rename to
WinPE, ready to fix OneDrive
- Run the following in the shell:
REG LOAD "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT" REG DELETE "HKU\DefaultUser\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "OneDriveSetup" /f REG UNLOAD "HKU\DefaultUser"
- Eject the DVD media once more and adjust the boot order again to the final configuration with
bootmgfw.efi
at the top, I preferFile, HDD, Network, DVD Drive
. - Reboot the VM and let it continue Windows Setup
- Wait for
Installing Windows
to complete- If all goes well, the VM will restart (possibly several times) and go in to OOBE (Out of Box Experience), and if you check
Settings → Firmware
you'll notice the boot order is updated withbootmgfw.efi
at the top. - Wait for
Let's start with region. Is this right?
From OOBE to Audit Mode
- On the
Let's start with region. Is this right?
screen, pressCTRL+SHIFT+F3
- You should see
Just a moment…
and the VM should restart - You should end up logged in as
Administrator
, with the Sysprep (System Preparation Tool) window open (it will come up after every restart, until we finally use it) - Click
Cancel
to quit Sysprep Shutdown
Windows so we can checkpoint the VM here- Create a Checkpoint, rename to
(timestamp) - Audit Mode
Disable Microsoft consumer experiences
Run → gpedit.msc → Computer Configuration → Administrative Templates → Windows Components → Cloud Content
- Enable
Turn off Microsoft consumer experiences
Restart
Windows
Enable the Network Adapter
VM Settings → Network Adapter → Virtual switch: Hyper-V Virtual Switch
- Answer
No
to network discovery prompt - Good idea to eject the Windows 10 media if you haven't already
Media → DVD Drive → Eject
Fix time
Start → Settings → Time & Language
- Time zone:
Eastern Time
- Enable
Set time automatically
- Enable
Set time zone automatically
- Confirm clock is accurate
Rename Computer
Shutdown
Windows- Create a Checkpoint, rename to
(timestamp) - Pre-Cleanup
Cleanup Libraries & Public Folder
Windows Explorer → View → Options
General
tab- Open File Explorer to:
This PC
- In
Privacy
section, clickClear
View
tab[ ] Hide empty drives
[ ] Hide extensions
[x] Expand to open folder
[x] Show all folders
[x] Show libraries
- Click
Ok
Windows Explorer → Libraries
- Select all libraries and delete them (they'll regenerate later)
Windows Explorer → This PC → C:\Users\Public
- Select all folders and delete them
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Cleanup1
Cleanup Appx Packages
Provisioned Windows 10 apps are documented here.
NOTE: All actions should be performed in an elevated PowerShell
console.
$packages = @( "Microsoft.BingWeather", "Microsoft.DesktopAppInstaller", "Microsoft.GetHelp", "Microsoft.Getstarted", "Microsoft.Messaging", "Microsoft.Microsoft3DViewer", "Microsoft.MicrosoftOfficeHub", "Microsoft.MicrosoftSolitaireCollection", "Microsoft.MixedReality.Portal", "Microsoft.MSPaint", "Microsoft.Office.OneNote", "Microsoft.OneConnect", "Microsoft.People", "Microsoft.Print3D", "Microsoft.Wallet", "microsoft.windowscommunicationsapps", "Microsoft.WindowsFeedbackHub", "Microsoft.WindowsMaps", "Microsoft.Xbox.TCUI", "Microsoft.XboxApp", "Microsoft.XboxGameOverlay", "Microsoft.XboxGamingOverlay", "Microsoft.XboxIdentityProvider", "Microsoft.XboxSpeechToTextOverlay", "Microsoft.YourPhone", "Microsoft.ZuneMusic", "Microsoft.ZuneVideo" ) Get-AppxProvisionedPackage -Online | Where-Object { $packages -contains $_.DisplayName } | Remove-AppxProvisionedPackage -Online Get-AppxPackage -AllUsers | Where-Object { $packages -contains $_.Name } | Remove-AppxPackage -AllUsers
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Cleanup2
Cleanup OneDrive
OneDrive has a proper Uninstaller in 1809, and (as of time of this documentation) running the cleanup script alone leaves the uninstall entry orphaned in Programs and Features, along with some shortcuts in the start menu.
Win+X → Apps and Features
- Search for
OneDrive
andUninstall
it, and close theSettings
window- It may look like it's not doing anything at first, it's probably updating to the latest OneDrive version first. Give it a few min, and then try to Uninstall again, it should clear out.
- Run the below cleanup script
Stole this code from here.
NOTE: This should be performed in an elevated PowerShell
console.
function Takeown-File($path) { takeown.exe /A /F $path $acl = Get-Acl $path # get administraor group $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") $admins = $admins.Translate([System.Security.Principal.NTAccount]) # add NT Authority\SYSTEM $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($admins, "FullControl", "None", "None", "Allow") $acl.AddAccessRule($rule) Set-Acl -Path $path -AclObject $acl } function Takeown-Folder($path) { Takeown-File $path foreach ($item in Get-ChildItem $path) { if (Test-Path $item -PathType Container) { Takeown-Folder $item.FullName } else { Takeown-File $item.FullName } } } Write-Output "Kill OneDrive process" taskkill.exe /F /IM "OneDrive.exe" taskkill.exe /F /IM "explorer.exe" Write-Output "Remove OneDrive" if (Test-Path "$env:systemroot\System32\OneDriveSetup.exe") { & "$env:systemroot\System32\OneDriveSetup.exe" /uninstall } if (Test-Path "$env:systemroot\SysWOW64\OneDriveSetup.exe") { & "$env:systemroot\SysWOW64\OneDriveSetup.exe" /uninstall } Write-Output "Removing OneDrive leftovers" Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:localappdata\Microsoft\OneDrive" Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:programdata\Microsoft OneDrive" Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:systemdrive\OneDriveTemp" # check if directory is empty before removing: If ((Get-ChildItem "$env:userprofile\OneDrive" -Recurse | Measure-Object).Count -eq 0) { Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:userprofile\OneDrive" } Write-Output "Remove Onedrive from explorer sidebar" New-PSDrive -PSProvider "Registry" -Root "HKEY_CLASSES_ROOT" -Name "HKCR" mkdir -Force "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" Set-ItemProperty "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 mkdir -Force "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" Set-ItemProperty "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 Remove-PSDrive "HKCR" Write-Output "Removing run hook for new users" reg load "hku\Default" "C:\Users\Default\NTUSER.DAT" reg delete "HKEY_USERS\Default\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "OneDriveSetup" /f reg unload "hku\Default" Write-Output "Removing startmenu entry" Remove-Item -Force -ErrorAction SilentlyContinue "$env:userprofile\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk" Write-Output "Removing scheduled task" Get-ScheduledTask -TaskPath '\' -TaskName 'OneDrive*' -ea SilentlyContinue | Unregister-ScheduledTask -Confirm:$false Write-Output "Restarting explorer" Start-Process "explorer.exe" Write-Output "Waiting for explorer to complete loading" Start-Sleep 10 Write-Output "Removing additional OneDrive leftovers" foreach ($item in (Get-ChildItem "$env:WinDir\WinSxS\*onedrive*")) { Takeown-Folder $item.FullName Remove-Item -Recurse -Force $item.FullName }
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Cleanup3
Cleanup Start/Taskbar
- Unpin all shortcuts from the
Start Menu
andTaskbar
, and remove any Desktop shortcuts, except forRecycle Bin
. - Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Cleanup4
Deploy .NET 3.5
Win+X → Apps and Features → Programs and Features (at the bottom)
- Click
Turn Windows features on or off
- Click once on tick
.NET Framework 3.5 (includes .NET 2.0 and 3.0)
- Click
OK
and thenLet Windows Update download the files for you
- If this method fails, you'll need to use DISM:
- Mount the Win10 installation ISO
- Open elevated shell prompt and run the command:
dism /online /enable-feature /featurename:NetFX3 /All /Source:D:\sources\sxs /LimitAccess
- The
D:\
above is the drive letter of the mounted ISO
- Close all windows once requested changes are completed
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - .NET 3.5
Deploy VC++ Runtimes
I've aggregated the runtime installers from these official and unofficial listings. I keep them on the MDT server in \_prep\_apps\VC++ Runtimes
.
- Run all of the installers in order
- The VC2005 x64 installer drops
msdia80.dll
to the root of the biggest disk, so clean that up:- Move
C:\msdia80.dll
toC:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll
- Run:
regsvr32 "C:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll"
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - VC++ Runtimes
Activate Windows
Customization via the Settings
app, along with some other features, will not be available without activating Windows. In order to activate in Audit Mode
we need to use slmgr
.
Run the following at an elevated prompt:
slmgr /ipk <product key>
After confirmation pop-up, run:
slmgr /ato
After confirmation pop-up, run:
slmgr /dli
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Activated
Customize User Experience
Right-Click empty space on the Task Bar → Task Manager
- Click
More details
, this will become the default view now
Right-Click empty space on the Task Bar → Cortana → Show Cortana icon
Right-Click empty space on the Task Bar → Taskbar settings
On
Lock the taskbarOff
Automatically hide the taskbar in desktop modeOff
Automatically hide the taskbar in tablet modeOff
Use small taskbar buttonsOn
Use PeekOn
Replace Command Prompt with Windows PowerShellOn
Show badges on taskbar buttons- Taskbar location on screen:
Bottom
- Combine taskbar buttons:
Always, hide labels
Notification area → Select which icons appear on the taskbar
On
Always show all icons in the notification area- Click
←
Off
Show contacts on the taskbar
Personalization → Start
Off
Show more tiles on StartOn
Show app list in Start menuOff
Show recently added appsOff
Show most used appsOff
Use Start full screenOn
Show recently opened items in Jump Lists on Start or the taskbarChoose which folders appear on Start
On
File ExplorerOn
SettingsOn
DocumentsOn
DownloadsOff
MusicOn
PicturesOff
VideosOff
NetworkOn
Personal folder- Click
←
Personalization → Colors
- Choose your default app mode:
Dark
Home → Apps → Default apps
- Web browser:
Internet Explorer
Home → System → Power & sleep
- Screen: When plugged in, turn off after:
15 min
- In order to load the Start and Taskbar pinned item layout in to new user profiles, we'll need to export/import the layout.
- To export the layout do:
Export-StartLayout -UseDesktopApplicationID -Path "\\MDT-Server\_prep\_startlayouts\layout.xml"
- Modify
layout.xml
according to the documentation available here in order to further customize it. For example, taskbar pinned items are not exported and need to be added manually. - For reference, here is the XML for the layout I prefer, which clears all the pinned items from the Start menu and Taskbar:
<?xml version="1.0" encoding="utf-8"?> <LayoutModificationTemplate xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification" xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout" Version="1"> <LayoutOptions StartTileGroupCellWidth="6" /> <DefaultLayoutOverride> <StartLayoutCollection> <defaultlayout:StartLayout GroupCellWidth="6" /> </StartLayoutCollection> </DefaultLayoutOverride> <CustomTaskbarLayoutCollection PinListPlacement="Replace"> <defaultlayout:TaskbarLayout> <taskbar:TaskbarPinList> <taskbar:DesktopApp DesktopApplicationLinkPath="#leaveempty" /> </taskbar:TaskbarPinList> </defaultlayout:TaskbarLayout> </CustomTaskbarLayoutCollection> </LayoutModificationTemplate>
- To import the layout do:
Import-Startlayout -LayoutPath "\\MDT-Server\_prep\_startlayouts\layout.xml" -MountPath $env:SystemDrive\
- Because we're going to be using copyprofile in our deployment answer file, we need to also import the layout in to the current
Administrator
profile.- To do this, run:
Copy-Item -Path "\\MDT-Server\_prep\_startlayouts\layout.xml" -Destination $env:LOCALAPPDATA\Microsoft\Windows\Shell\LayoutModification.xml
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - CustomUE
Customize Internet Explorer
- Launch
Internet Explorer
- Select
Use recommended security and compatibility settings
Gear → Internet Options → Advanced
- Click
Restore advanced settings
- Click
Apply
- Click
Reset
,[x] Delete personal settings
,Reset
- Restart
Internet Explorer
Gear → Internet Options
General
- Homepage
https://www.google.com
Security
Internet
zone[ ] Enable Protected Mode
Trusted sites
zone- Slide security level to
low
- Click
Sites
[ ] Require server verification
- Add
*.ufl.edu
[x] Require server verification
- Click
Close
Privacy
Pop-up Blocker → Settings
- Add
*.ufl.edu
- Click
Close
Programs
- HTML editor
Notepad
- Click
Manage add-ons
Accelerators
- Remove all the accelerators in the list
Search Providers
- Click
Find more search providers
- Add
Google Search
- Add:
EasyList Standard
- Close the new window
Close
Manage add-ons
- Click
Manage add-ons
againSearch Providers
- Set
Google
as default and deleteBing
Tracking Protection
- Confirm
EasyList
is shown and Enabled
Close
Manage add-ons
Ok
Internet Options- Confirm any warning
- Close and open
Internet Explorer
a few times to make sure you get to clear any lingering warnings/popups about the current settings - Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - CustomIE
Configure and Run Windows Updates
Start → Settings → Update & Security
Change active hours → 6am - 8pm
Advanced options
- Enable
Give me updates for other Microsoft products when I update Windows.
- Enable
Show a notification when your PC requires a restart to finish updating
- Click
←
in upper left to return to Windows Update screen
Check for updates
- Updates will automatically download and install
- May need to restart and retry
Check for updates
to confirm nothing remains pending
Shutdown
Windows- Create a Checkpoint, rename to
(timestamp) - WU
[OPTIONAL] - Cisco VPN (UF)
I keep the MSI
's on the MDT server in \_prep\_apps\VPN
.
- Deploy the following in this order:
anyconnect-win-4.6.01103-vpn-predeploy-k9.msi anyconnect-win-4.6.01103-gina-predeploy-k9.msi
- The
Gina
installer will ask to restart, go ahead and restart - Find the
Cisco AnyConnect
icon in the system tray and click it to open the connection window- Type in
vpn.ufl.edu
andConnect
- This first connection will get the latest configuration profile, and will also update the client, if it's out of date, and may ask to restart
- Click the
Cisco AnyConnect
icon in the system tray againDisconnect
and then switch to profileGatorlink VPN
andConnect
- Click the
Cisco AnyConnect
icon in the system tray one last timeDisconnect
and close the window
- We need to clean our account name from the cache
- Edit
c:\users\administrator\appdata\local\cisco\cisco anyconnect secure mobility client\preferences.xml
- Clean out the account name from the
<DefaultUser></DefaultUser>
tag so it's empty Save
and close the file
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - VPN
Final Online Cleanup
De-Activate Windows
Sysprep will not clear the activation key we used earlier, so we need to de-activate manually.
Run the following at an elevated prompt:
slmgr /upk
After confirmation pop-up, run:
slmgr /cpky
PowerShell History
We don't want every new profile to have our PowerShell
history, so clear it by running:
Clear-History Remove-Item (Get-PSReadlineOption).HistorySavePath
CCleaner
I have a good track record using CCleaner
to sanitize a system prior to Sysprep, so I keep a portable version on the MDT server in \_prep\_apps\CCleaner_portable
.
- Open
CCleaner
and ensure the following settingsOptions → Settings
- CCleaner Home Screen
Custom Clean
Options → Updates
- Uncheck all the options
Options → Advanced
- Uncheck all the options, except:
[x] Hide warning messages
[x] Save all settings to INI file
[x] Skip User Account Control warning
Options → Privacy
- Uncheck all the options
Custom Clean → Windows
- Enable all options by double clicking the root categories, accept any warnings
- Uncheck
Wipe Free Space
underAdvanced
Custom Clean → Applications
- Enable all options by double clicking the root categories
- Once ready to clean up…
Custom Clean → Run Cleaner
[x] Do not show me this message again
andContinue/Yes/Ok
if any warnings come up- If any errors about
Edge
come up, just terminate it viaTask Manager
andRun Cleaner
again
Run Cleaner
a few times to confirm nothing is left overRegistry → Scan for Issues → Fix selected issues…
- Repeat a few times to confirm nothing is left over
- Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - Final Cleanup
Capture Phase 1 - Sysprep
Since our goal is to use copyprofile, we need a prepared XML answer file to feed Sysprep
. Here is what that looks like:
- sysprep_CopyProfile.xml
<?xml version="1.0" encoding="utf-8"?> <unattend xmlns="urn:schemas-microsoft-com:unattend"> <settings pass="specialize"> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <CopyProfile>true</CopyProfile> </component> </settings> </unattend>
To simplify executing Sysprep
correctly, every time, I prepared the following batch file:
- sysprep_CopyProfile.bat
@echo off set DRIVE=%~d0 set PATH=%~p0 @echo on %windir%\system32\sysprep\sysprep.exe /generalize /oobe /shutdown /unattend:%DRIVE%%PATH%sysprep_CopyProfile.xml
- I keep both the XML and the batch file on the MDT server, so to kick off
Sysprep
I run\\MDT-Server\_prep\_sysprep\sysprep_CopyProfile.bat
Sysprep
should run without any issues and then shutdown Windows- Create a Checkpoint, rename to
(timestamp) - SYSPREP
Capture Phase 2 - Profile Cleanup
Copyprofile is going to copy a variety of content from the Administrator
profile to the Default
profile. Some of this content will be polluted due to our time in Audit Mode
, and will corrupt Edge
and possibly other apps for new profiles.
We need to clean out this content, and it is best to do this in WinPE
after Sysprep
, so none of the content is locked by running processes.
While we're doing this, may as well clean up some other items, if they exist.
- Boot the VM into
WinPE
, I use a mountable ISO from our MDT environment- Mount the ISO and update the
Firmware → Boot Order
of the VM so theDVD Drive
is at the top
- Perform the following in the shell:
# Launch PowerShell powershell # Cleanup necessary for proper function foreach ($item in @( "C:\Users\Administrator\.cisco\", "C:\Users\Administrator\3D Objects\", "C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\", "C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\", "C:\Users\Administrator\AppData\Local\Microsoft\Windows\WebCache\", "C:\Users\Administrator\AppData\Local\Microsoft\Windows\WebCacheLock.dat", "C:\Users\Administrator\AppData\Local\MicrosoftEdge\", "C:\Users\Administrator\Favorites\*", "C:\Users\Administrator\Contacts\", "C:\Users\Administrator\OneDrive\", "C:\Users\Administrator\Searches\", "C:\Users\Default\AppData\Local\Microsoft\WindowsApps\", "C:\Users\Default\AppData\Local\Microsoft\Windows\INetCache\", "C:\Users\Default\Favorites\*", "C:\Users\Default\*.log", "C:\Users\Default\*.blf", "C:\Users\Default\*.REGTRANS-MS", "C:\Users\Public\" )) { if ($item -match "^.*\*$") { Get-ChildItem $item -Force | Remove-Item -Force -Recurse -Verbose } else { Remove-Item $item -Force -Recurse -Verbose } } # Registry cleanup per Important block documented here: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/customize-the-default-user-profile-by-using-copyprofile REG LOAD HKU\DefaultUser "C:\Users\Default\NTUSER.DAT" REG LOAD HKU\AdminUser "C:\Users\Administrator\NTUSER.DAT" REG DELETE "HKU\DefaultUser\Software\Microsoft\Windows\Shell\Associations" /v "FileAssociationsUpdateVersion" /f REG DELETE "HKU\DefaultUser\Software\Microsoft\Windows\Shell\Associations\UrlAssociations" /f REG DELETE "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts" /f REG DELETE "HKU\AdminUser\Software\Microsoft\Windows\Shell\Associations" /v "FileAssociationsUpdateVersion" /f REG DELETE "HKU\AdminUser\Software\Microsoft\Windows\Shell\Associations\UrlAssociations" /f REG DELETE "HKU\AdminUser\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts" /f REG UNLOAD HKU\DefaultUser REG UNLOAD HKU\AdminUser # Remove OneDrive File Explorer pin REG LOAD HKLM\TempSoftware "C:\Windows\System32\config\SOFTWARE" REG ADD "HKLM\TempSoftware\Classes\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f /v "System.IsPinnedToNameSpaceTree" /t REG_DWORD /d 0 REG ADD "HKLM\TempSoftware\Wow6432Node\Classes\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f /v "System.IsPinnedToNameSpaceTree" /t REG_DWORD /d 0 REG UNLOAD HKLM\TempSoftware # OPTIONAL cleanup for slimmer profiles - WILL REMOVE POTENTIALLY DESIREABLE PER-USER APPLICATION CUSTOMIZATION/DATA @( $(Get-ChildItem "C:\Users\Administrator\AppData\LocalLow" -Force), $(Get-ChildItem "C:\Users\Administrator\AppData\Local\Microsoft\Windows" -Force -Exclude "Shell", "WinX"), $(Get-ChildItem "C:\Users\Administrator\AppData\Local\Microsoft" -Force -Exclude "Windows"), $(Get-ChildItem "C:\Users\Administrator\AppData\Local" -Force -Exclude "Microsoft" ), $(Get-ChildItem "C:\Users\Administrator\AppData\Roaming\Microsoft\Windows" -Force -Exclude "Start Menu", "SendTo"), $(Get-ChildItem "C:\Users\Administrator\AppData\Roaming\Microsoft" -Force -Exclude "Windows"), $(Get-ChildItem "C:\Users\Administrator\AppData\Roaming" -Force -Exclude "Microsoft" ) $(Get-ChildItem "C:\Users\Default\AppData\LocalLow" -Force), $(Get-ChildItem "C:\Users\Default\AppData\Local\Microsoft\Windows" -Force -Exclude "Shell", "WinX"), $(Get-ChildItem "C:\Users\Default\AppData\Local\Microsoft" -Force -Exclude "Windows"), $(Get-ChildItem "C:\Users\Default\AppData\Local" -Force -Exclude "Microsoft" ), $(Get-ChildItem "C:\Users\Default\AppData\Roaming\Microsoft\Windows" -Force -Exclude "Start Menu", "SendTo"), $(Get-ChildItem "C:\Users\Default\AppData\Roaming\Microsoft" -Force -Exclude "Windows"), $(Get-ChildItem "C:\Users\Default\AppData\Roaming" -Force -Exclude "Microsoft" ) ) | ForEach-Object { Remove-Item $PSItem.fullname -Force -Recurse -Verbose }
- Stay in
WinPE
for Capture Phase 3 - Create a Live Checkpoint (don't shutdown), rename to
(timestamp) - Live - WinPE Profile Cleanup
Capture Phase 3 - Capture the WIM
- First we need to mount our capture directory:
net use z: \\MDT-Server\_wimcap
- Then we need to capture the WIM:
dism /capture-image /imagefile:z:\Win10Ent_x64_1809.wim /capturedir:c:\ /name:"Windows 10 Enterprise - Customized" /compress:maximum