Lore

If it's worth remembering, it's worth writing down, if I find the time, and remember...

User Tools

Site Tools


referenceimage

This is an old revision of the document!


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.

  1. Create a VM to host the reference build, perform vanilla Windows setup from an ISO, and get in to Audit Mode.
  2. Perform a variety of configuration changes, cleanup, software/utility additions, and Windows Updates to establish a desirable baseline.
  3. Take snapshots at critical points throughout the process for convenient roll-back.
  4. 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

  1. New → Virtual Machine
  2. Specify Name and Location
    1. Example name pattern Windows10_Reference
  3. Specify Generation
    1. Select Generation 2 for 64bit UEFI operating systems, otherwise stick to Generation 1
  4. Assign Memory
    1. Startup Memory 2048
    2. [x] Use Dynamic Memory
  5. Configure Networking
    1. Connection Not Connected
  6. Connect Virtual Hard Disk
    1. Leave (x) Create a virtual hard disk selected with defaults, should be creating a 127 GB disk.
  7. Installation Options
    1. Select Install an operating system later
  8. Finish
  9. Right-Click → Settings on the new VM
  10. Processor
    1. Number of virtual processors 2
  11. Firmware
    1. Boot order, set it to Network, HDD
  12. Integration Services
    1. Enable all
  13. Checkpoints
    1. Set Checkpoint Type to Standard checkpoints
    2. Set Checkpoint File Location to a dedicated path if using non-default.
    3. Ex: D:\_hyperv\_checkpoints
  14. Smart Paging File Location
    1. Set Smart Paging file location to a dedicated path if using non-default.
    2. Ex: D:\_hyperv\_paging
  15. Close VM Settings
  16. Create a Checkpoint, rename to Fresh VM - 2GB dynamic RAM, 2 Cores

Initial Windows 10 Deployment

  1. 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.
    1. Right-Click → Settings on the new VM
    2. SCSI Controller
      1. DVD Drive → Add → Apply
    3. Firmware
      1. Boot order, set it to DVD Drive, Network, HDD and OK
  2. Right-Click → Connect on the VM to connect to its console
  3. Media → DVD Drive → Insert Disk… and mount the appropriate Windows ISO
  4. Start the VM, don't miss the Press any key… prompt or you'll miss setup and need to restart the VM
  5. Windows Setup
    1. Next → Install now
    2. If prompted, select the appropriate operating system edition you want to install, ex: Windows 10 Enterprise
    3. [x] I accept the license terms and Next
  6. Select Custom: Install Windows only (advanced)
  7. Should see Drive 0 Unallocated Space 127 GB so Next
  8. 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.
    1. When setup gets to Windows needs to restart to continue force shutdown the VM.
    2. Create a Checkpoint, rename to Windows Setup, first reboot
    3. Eject the OS install media and insert WinPE media instead.
    4. Push DVD Drive to the top of the boot order again.
    5. Boot to the WinPE media and create a Checkpoint, rename to WinPE, ready to fix OneDrive
    6. 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"
    7. Eject the DVD media once more and adjust the boot order again to the final configuration with bootmgfw.efi at the top, I prefer File, HDD, Network, DVD Drive.
    8. Reboot the VM and let it continue Windows Setup
  9. Wait for Installing Windows to complete
    1. 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 with bootmgfw.efi at the top.
    2. Wait for Let's start with region. Is this right?

From OOBE to Audit Mode

  1. On the Let's start with region. Is this right? screen, press CTRL+SHIFT+F3
  2. You should see Just a moment… and the VM should restart
  3. 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)
  4. Click Cancel to quit Sysprep
  5. Shutdown Windows so we can checkpoint the VM here
  6. Create a Checkpoint, rename to (timestamp) - Audit Mode

Disable Microsoft consumer experiences

  1. Run → gpedit.msc → Computer Configuration → Administrative Templates → Windows Components → Cloud Content
    1. Enable Turn off Microsoft consumer experiences
  2. Restart Windows

Enable the Network Adapter

  1. VM Settings → Network Adapter → Virtual switch: Hyper-V Virtual Switch
  2. Answer No to network discovery prompt
  3. Good idea to eject the Windows 10 media if you haven't already Media → DVD Drive → Eject

Fix time

  1. Start → Settings → Time & Language
  2. Time zone: Eastern Time
  3. Enable Set time automatically
  4. Enable Set time zone automatically
  5. Confirm clock is accurate

Rename Computer

  1. Run this in an elevated CMD to change the Workgroup to set this machine apart, if desired, and rename it:
    wmic computersystem where name="%computername%" call rename name="Win10Ent_1809"
    wmic computersystem where name="%computername%" call joindomainorworkgroup name="NewWorkgroup"
  2. Shutdown Windows
  3. Create a Checkpoint, rename to (timestamp) - Pre-Cleanup

Cleanup Libraries & Public Folder

  1. Windows Explorer → View → Options
    1. General tab
      1. Open File Explorer to: This PC
      2. In Privacy section, click Clear
    2. View tab
      1. [ ] Hide empty drives
      2. [ ] Hide extensions
      3. [x] Expand to open folder
      4. [x] Show all folders
      5. [x] Show libraries
    3. Click Ok
  2. Windows Explorer → Libraries
    1. Select all libraries and delete them (they'll regenerate later)
  3. Windows Explorer → This PC → C:\Users\Public
    1. Select all folders and delete them
  4. 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.

  1. Win+X → Apps and Features
  2. Search for OneDrive and Uninstall it, and close the Settings window
    1. 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.
  3. 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

  1. Unpin all shortcuts from the Start Menu and Taskbar, and remove any Desktop shortcuts, except for Recycle Bin.
  2. Create a Live Checkpoint (don't shutdown), rename to (timestamp) - Live - Cleanup4

Deploy .NET 3.5

  1. Win+X → Apps and Features → Programs and Features (at the bottom)
  2. Click Turn Windows features on or off
  3. Click once on tick .NET Framework 3.5 (includes .NET 2.0 and 3.0)
  4. Click OK and then Let Windows Update download the files for you
    1. If this method fails, you'll need to use DISM:
      1. Mount the Win10 installation ISO
      2. Open elevated shell prompt and run the command:
        dism /online /enable-feature /featurename:NetFX3 /All /Source:D:\sources\sxs /LimitAccess
      3. The D:\ above is the drive letter of the mounted ISO
  5. Close all windows once requested changes are completed
  6. 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.

  1. Run all of the installers in order
    1. The VC2005 x64 installer drops msdia80.dll to the root of the biggest disk, so clean that up:
      1. Move C:\msdia80.dll to C:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll
      2. Run:
        regsvr32 "C:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll"
  2. 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

  1. Right-Click empty space on the Task Bar → Task Manager
    1. Click More details, this will become the default view now
  2. Right-Click empty space on the Task Bar → Cortana → Show Cortana icon
  3. Right-Click empty space on the Task Bar → Taskbar settings
    1. On Lock the taskbar
    2. Off Automatically hide the taskbar in desktop mode
    3. Off Automatically hide the taskbar in tablet mode
    4. Off Use small taskbar buttons
    5. On Use Peek
    6. On Replace Command Prompt with Windows PowerShell
    7. On Show badges on taskbar buttons
    8. Taskbar location on screen: Bottom
    9. Combine taskbar buttons: Always, hide labels
    10. Notification area → Select which icons appear on the taskbar
      1. On Always show all icons in the notification area
      2. Click
    11. Off Show contacts on the taskbar
  4. Personalization → Start
    1. Off Show more tiles on Start
    2. On Show app list in Start menu
    3. Off Show recently added apps
    4. Off Show most used apps
    5. Off Use Start full screen
    6. On Show recently opened items in Jump Lists on Start or the taskbar
    7. Choose which folders appear on Start
      1. On File Explorer
      2. On Settings
      3. On Documents
      4. On Downloads
      5. Off Music
      6. On Pictures
      7. Off Videos
      8. Off Network
      9. On Personal folder
      10. Click
  5. Personalization → Colors
    1. Choose your default app mode: Dark
  6. Home → Apps → Default apps
    1. Web browser: Internet Explorer
  7. Home → System → Power & sleep
    1. Screen: When plugged in, turn off after: 15 min
  8. In order to load the Start and Taskbar pinned item layout in to new user profiles, we'll need to export/import the layout.
    1. To export the layout do:
      Export-StartLayout -UseDesktopApplicationID -Path "\\MDT-Server\_prep\_startlayouts\layout.xml"
    2. 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.
    3. 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>
    4. To import the layout do:
      Import-Startlayout -LayoutPath "\\MDT-Server\_prep\_startlayouts\layout.xml" -MountPath $env:SystemDrive\
  9. 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.
    1. To do this, run:
      Copy-Item -Path "\\MDT-Server\_prep\_startlayouts\layout.xml" -Destination $env:LOCALAPPDATA\Microsoft\Windows\Shell\LayoutModification.xml
  10. Create a Live Checkpoint (don't shutdown), rename to (timestamp) - Live - CustomUE

Customize Internet Explorer

  1. Launch Internet Explorer
  2. Select Use recommended security and compatibility settings
  3. Gear → Internet Options → Advanced
    1. Click Restore advanced settings
    2. Click Apply
    3. Click Reset, [x] Delete personal settings, Reset
  4. Restart Internet Explorer
  5. Gear → Internet Options
    1. General
    2. Security
      1. Internet zone
        1. [ ] Enable Protected Mode
      2. Trusted sites zone
        1. Slide security level to low
        2. Click Sites
          1. [ ] Require server verification
          2. Add *.ufl.edu
          3. [x] Require server verification
          4. Click Close
    3. Privacy
      1. Pop-up Blocker → Settings
        1. Add *.ufl.edu
        2. Click Close
    4. Programs
      1. HTML editor Notepad
  6. Click Manage add-ons
    1. Accelerators
      1. Remove all the accelerators in the list
    2. Search Providers
      1. Click Find more search providers
        1. Add Google Search
        2. Add: EasyList Standard
        3. Close the new window
    3. Close Manage add-ons
  7. Click Manage add-ons again
    1. Search Providers
      1. Set Google as default and delete Bing
    2. Tracking Protection
      1. Confirm EasyList is shown and Enabled
    3. Close Manage add-ons
  8. Ok Internet Options
  9. Confirm any warning
  10. Close and open Internet Explorer a few times to make sure you get to clear any lingering warnings/popups about the current settings
  11. Create a Live Checkpoint (don't shutdown), rename to (timestamp) - Live - CustomIE

Configure and Run Windows Updates

  1. Start → Settings → Update & Security
  2. Change active hours → 6am - 8pm
  3. Advanced options
    1. Enable Give me updates for other Microsoft products when I update Windows.
    2. Enable Show a notification when your PC requires a restart to finish updating
    3. Click in upper left to return to Windows Update screen
  4. Check for updates
    1. Updates will automatically download and install
    2. May need to restart and retry Check for updates to confirm nothing remains pending
  5. Shutdown Windows
  6. Create a Checkpoint, rename to (timestamp) - WU

[OPTIONAL] - Cisco VPN (UF)

I keep the MSI's on the MDT server in \_prep\_apps\VPN.

  1. Deploy the following in this order:
    anyconnect-win-4.6.01103-vpn-predeploy-k9.msi
    anyconnect-win-4.6.01103-gina-predeploy-k9.msi
  2. The Gina installer will ask to restart, go ahead and restart
  3. Find the Cisco AnyConnect icon in the system tray and click it to open the connection window
    1. Type in vpn.ufl.edu and Connect
      1. 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
  4. Click the Cisco AnyConnect icon in the system tray again
    1. Disconnect and then switch to profile Gatorlink VPN and Connect
  5. Click the Cisco AnyConnect icon in the system tray one last time
    1. Disconnect and close the window
  6. We need to clean our account name from the cache
    1. Edit c:\users\administrator\appdata\local\cisco\cisco anyconnect secure mobility client\preferences.xml
      1. Clean out the account name from the <DefaultUser></DefaultUser> tag so it's empty
      2. Save and close the file
  7. 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.

  1. Open CCleaner and ensure the following settings
    1. Options → Settings
      1. CCleaner Home Screen Custom Clean
    2. Options → Updates
      1. Uncheck all the options
    3. Options → Advanced
      1. Uncheck all the options, except:
        1. [x] Hide warning messages
        2. [x] Save all settings to INI file
        3. [x] Skip User Account Control warning
    4. Options → Privacy
      1. Uncheck all the options
    5. Custom Clean → Windows
      1. Enable all options by double clicking the root categories, accept any warnings
      2. Uncheck Wipe Free Space under Advanced
    6. Custom Clean → Applications
      1. Enable all options by double clicking the root categories
  2. Once ready to clean up…
    1. Custom Clean → Run Cleaner
      1. [x] Do not show me this message again and Continue/Yes/Ok if any warnings come up
      2. If any errors about Edge come up, just terminate it via Task Manager and Run Cleaner again
    2. Run Cleaner a few times to confirm nothing is left over
    3. Registry → Scan for Issues → Fix selected issues…
      1. Repeat a few times to confirm nothing is left over
  3. 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
  1. 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
  2. Sysprep should run without any issues and then shutdown Windows
  3. 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.

  1. Boot the VM into WinPE, I use a mountable ISO from our MDT environment
    1. Mount the ISO and update the Firmware → Boot Order of the VM so the DVD Drive is at the top
  2. 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 }
  3. Stay in WinPE for Capture Phase 3
  4. Create a Live Checkpoint (don't shutdown), rename to (timestamp) - Live - WinPE Profile Cleanup

Capture Phase 3 - Capture the WIM

  1. First we need to mount our capture directory:
    net use z: \\MDT-Server\_wimcap
  2. 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
referenceimage.1592856663.txt.gz · Last modified: 2020/06/22 16:11 by thekojukinator