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 2for 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 diskselected with defaults, should be creating a127 GBdisk.
- Installation Options
- Select
Install an operating system later
FinishRight-Click → Settingson 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 → Settingson the new VM- SCSI Controller
DVD Drive → Add → Apply
- Firmware
- Boot order, set it to
DVD Drive, Network, HDDandOK
Right-Click → Connecton the VM to connect to its consoleMedia → DVD Drive → Insert Disk…and mount the appropriate Windows ISOStartthe 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 termsandNext
- Select
Custom: Install Windows only (advanced) - Should see
Drive 0 Unallocated Space 127 GBsoNext - 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 continueforce shutdown the VM. - Take a snapshot
- Wait for
Installing Windowsto 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 → Firmwareyou'll notice the boot order is updated withbootmgfw.efiat 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
Cancelto quit Sysprep ShutdownWindows 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
RestartWindows
Enable the Network Adapter
VM Settings → Network Adapter → Virtual switch: Hyper-V Virtual Switch- Answer
Noto 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
ShutdownWindows- Create a Checkpoint, rename to
(timestamp) - Pre-Cleanup
Cleanup Libraries & Public Folder
Windows Explorer → View → OptionsGeneraltab- Open File Explorer to:
This PC - In
Privacysection, clickClear
Viewtab[ ] 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
OneDriveandUninstallit, and close theSettingswindow- 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 MenuandTaskbar, 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
OKand 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.dllto the root of the biggest disk, so clean that up:- Move
C:\msdia80.dlltoC:\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 iconRight-Click empty space on the Task Bar → Taskbar settingsOnLock the taskbarOffAutomatically hide the taskbar in desktop modeOffAutomatically hide the taskbar in tablet modeOffUse small taskbar buttonsOnUse PeekOnReplace Command Prompt with Windows PowerShellOnShow badges on taskbar buttons- Taskbar location on screen:
Bottom - Combine taskbar buttons:
Always, hide labels Notification area → Select which icons appear on the taskbarOnAlways show all icons in the notification area- Click
←
OffShow contacts on the taskbar
Personalization → StartOffShow more tiles on StartOnShow app list in Start menuOffShow recently added appsOffShow most used appsOffUse Start full screenOnShow recently opened items in Jump Lists on Start or the taskbarChoose which folders appear on StartOnFile ExplorerOnSettingsOnDocumentsOnDownloadsOffMusicOnPicturesOffVideosOffNetworkOnPersonal 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.xmlaccording 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
Administratorprofile.- 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 OptionsGeneral- Homepage
https://www.google.com
SecurityInternetzone[ ] Enable Protected Mode
Trusted siteszone- Slide security level to
low - Click
Sites[ ] Require server verification- Add
*.ufl.edu [x] Require server verification- Click
Close
PrivacyPop-up Blocker → Settings- Add
*.ufl.edu - Click
Close
Programs- HTML editor
Notepad
- Click
Manage add-onsAccelerators- Remove all the accelerators in the list
Search Providers- Click
Find more search providers- Add
Google Search - Add:
EasyList Standard - Close the new window
CloseManage add-ons
- Click
Manage add-onsagainSearch Providers- Set
Googleas default and deleteBing
Tracking Protection- Confirm
EasyListis shown and Enabled
CloseManage add-ons
OkInternet Options- Confirm any warning
- Close and open
Internet Explorera 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 & SecurityChange active hours → 6am - 8pmAdvanced 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 updatesto confirm nothing remains pending
ShutdownWindows- 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
Ginainstaller will ask to restart, go ahead and restart - Find the
Cisco AnyConnecticon in the system tray and click it to open the connection window- Type in
vpn.ufl.eduandConnect- 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 AnyConnecticon in the system tray againDisconnectand then switch to profileGatorlink VPNandConnect
- Click the
Cisco AnyConnecticon in the system tray one last timeDisconnectand 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 Saveand 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
CCleanerand 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 SpaceunderAdvanced
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 againandContinue/Yes/Okif any warnings come up- If any errors about
Edgecome up, just terminate it viaTask ManagerandRun Cleaneragain
Run Cleanera 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
SysprepI run\\MDT-Server\_prep\_sysprep\sysprep_CopyProfile.bat Sysprepshould 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 Orderof the VM so theDVD Driveis 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
WinPEfor 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