====== 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.
- Sysprep and capture the disk image.
- Take snapshots at critical points throughout the process for convenient roll-back.
===== Software Used =====
* [[https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/about/|Hyper-V]] - My virtualization environment of choice as it is freely available on Windows.
* [[https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install|Windows ADK]] - Requisite for WDS/MDT, but also a required toolkit to prepare a WinPE boot environment.
===== The Build (Windows 10 1809) =====
==== Creating a New Virtual Machine in Hyper-V ====
- ''New -> Virtual Machine''
- Specify Name and Location
- Example name pattern ''Win10Ent_1809_x64''
- Specify Generation
- Select ''Generation 2'' for 64bit UEFI operating systems, otherwise stick to ''Generation 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 a ''127 GB'' disk.
- Installation Options
- Select ''Install an operating system later''
- ''Finish''
- ''Right-Click -> Settings'' on the new VM
- Processor
- Number of virtual processors ''2''
- SCSI Controller
- ''DVD Drive -> Add''
- Firmware
- Boot order, set it to ''DVD, 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 ''(timestamp) - Fresh VM''
==== Initial Windows 10 Deployment ====
- ''Right-Click -> Connect'' on the new VM to connect to its console
- ''Media -> DVD Drive -> Insert Disk...'' and mount the appropriate Windows ISO
- ''Start'' the VM, don't miss the ''Press 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'' and ''Next''
- Select ''Custom: Install Windows only (advanced)''
- Should see ''Drive 0 Unallocated Space 127 GB'' so ''Next''
- 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 with ''bootmgfw.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, press ''CTRL+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 ====
- 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"
- ''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, click ''Clear''
- ''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 [[https://docs.microsoft.com/en-us/windows/application-management/apps-in-windows-10|here]].
NOTE: All actions should be performed in an elevated ''PowerShell'' console.
# To get deployed packages across all user profiles:
Get-AppxPackage -AllUsers | select PackageFullName| sort PackageFullName
# To get provisioned packages which are ready to deploy:
Get-AppxProvisionedPackage -Online | select PackageName | sort PackageName
# To remove deployed packages via partial name matching:
Get-AppxPackage -AllUsers | ?{$_.PackageFullName -like "*name*"} | Remove-AppxPackage
# To remove provisioned packages via partial name matching:
Get-AppxProvisionedPackage -Online | ?{$_.PackageName -like "*name*"} | Remove-AppxProvisionedPackage -online
# Here is a full dump of Get-AppxPackage and Get-AppxProvisionedPackage from build 1809,
# and packages that are not to be removed are commented out:
$appx = @(
#"1527c705-839a-4832-9118-54d4Bd6a0c89_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"c5e2524a-ea46-4f67-841f-6a9465d9d515_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"E2A4F912-2574-4A75-9BB0-0D023378592B_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"InputApp_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.AAD.BrokerPlugin_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.AccountsControl_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.Advertising.Xaml_10.1804.2.0_x64__8wekyb3d8bbwe"
#"Microsoft.Advertising.Xaml_10.1804.2.0_x86__8wekyb3d8bbwe"
#"Microsoft.AsyncTextService_10.0.17763.1_neutral__8wekyb3d8bbwe"
"Microsoft.BingWeather_4.25.12127.0_x64__8wekyb3d8bbwe"
#"Microsoft.BioEnrollment_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.CredDialogHost_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.DesktopAppInstaller_1.0.22011.0_x64__8wekyb3d8bbwe"
#"Microsoft.ECApp_10.0.17763.1_neutral__8wekyb3d8bbwe"
"Microsoft.GetHelp_10.1706.10441.0_x64__8wekyb3d8bbwe"
"Microsoft.Getstarted_6.13.11581.0_x64__8wekyb3d8bbwe"
#"Microsoft.HEIFImageExtension_1.0.11792.0_x64__8wekyb3d8bbwe"
#"Microsoft.LockApp_10.0.17763.1_neutral__cw5n1h2txyewy"
"Microsoft.Messaging_3.43.27001.0_x64__8wekyb3d8bbwe"
"Microsoft.Microsoft3DViewer_4.1808.15012.0_x64__8wekyb3d8bbwe"
#"Microsoft.MicrosoftEdge_44.17763.1.0_neutral__8wekyb3d8bbwe"
#"Microsoft.MicrosoftEdgeDevToolsClient_1000.17763.1.0_neutral_neutral_8wekyb3d8bbwe"
"Microsoft.MicrosoftOfficeHub_17.8918.5926.0_x64__8wekyb3d8bbwe"
"Microsoft.MicrosoftSolitaireCollection_4.1.5252.0_x86__8wekyb3d8bbwe"
#"Microsoft.MicrosoftStickyNotes_2.0.13.0_x64__8wekyb3d8bbwe"
"Microsoft.MixedReality.Portal_2000.18081.1242.0_x64__8wekyb3d8bbwe"
#"Microsoft.MSPaint_4.1807.12027.0_x64__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Framework.1.6_1.6.24903.0_x64__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Framework.1.6_1.6.24903.0_x86__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Framework.1.7_1.7.25531.0_x64__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Framework.1.7_1.7.25531.0_x86__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Runtime.1.6_1.6.24903.0_x64__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Runtime.1.6_1.6.24903.0_x86__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Runtime.1.7_1.7.25531.0_x64__8wekyb3d8bbwe"
#"Microsoft.NET.Native.Runtime.1.7_1.7.25531.0_x86__8wekyb3d8bbwe"
"Microsoft.Office.OneNote_16001.10228.20003.0_x64__8wekyb3d8bbwe"
"Microsoft.OneConnect_5.1807.1991.0_x64__8wekyb3d8bbwe"
"Microsoft.People_10.1805.1361.0_x64__8wekyb3d8bbwe"
#"Microsoft.PPIProjection_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Print3D_3.0.1521.0_x64__8wekyb3d8bbwe"
#"Microsoft.ScreenSketch_10.1806.2112.0_x64__8wekyb3d8bbwe"
#"Microsoft.Services.Store.Engagement_10.0.1610.0_x64__8wekyb3d8bbwe"
#"Microsoft.Services.Store.Engagement_10.0.1610.0_x86__8wekyb3d8bbwe"
#"Microsoft.SkypeApp_14.26.95.0_x64__kzf8qxf38zg5c"
#"Microsoft.StorePurchaseApp_11805.1001.8.0_x64__8wekyb3d8bbwe"
#"Microsoft.VCLibs.140.00_14.0.25426.0_x64__8wekyb3d8bbwe"
#"Microsoft.VCLibs.140.00_14.0.25426.0_x86__8wekyb3d8bbwe"
#"Microsoft.VP9VideoExtensions_1.0.12342.0_x64__8wekyb3d8bbwe"
"Microsoft.Wallet_2.2.18179.0_x64__8wekyb3d8bbwe"
#"Microsoft.WebMediaExtensions_1.0.12341.0_x64__8wekyb3d8bbwe"
#"Microsoft.WebpImageExtension_1.0.11551.0_x64__8wekyb3d8bbwe"
#"Microsoft.Win32WebViewHost_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.Apprep.ChxApp_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.AssignedAccessLockApp_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.CapturePicker_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.Windows.CloudExperienceHost_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.ContentDeliveryManager_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.Cortana_1.11.5.17763_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.NarratorQuickStart_10.0.17763.1_neutral_neutral_8wekyb3d8bbwe"
#"Microsoft.Windows.OOBENetworkCaptivePortal_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.Windows.OOBENetworkConnectionFlow_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.Windows.ParentalControls_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.PeopleExperienceHost_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.Photos_2018.18051.21218.0_x64__8wekyb3d8bbwe"
#"Microsoft.Windows.PinningConfirmationDialog_1000.17763.1.0_neutral__cw5n1h2txyewy"
#"Microsoft.Windows.SecHealthUI_10.0.17763.1_neutral__cw5n1h2txyewy"
#"Microsoft.Windows.SecureAssessmentBrowser_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.ShellExperienceHost_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.Windows.XGpuEjectDialog_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"Microsoft.WindowsAlarms_10.1805.1361.0_x64__8wekyb3d8bbwe"
#"Microsoft.WindowsCalculator_10.1805.1201.0_x64__8wekyb3d8bbwe"
#"Microsoft.WindowsCamera_2018.425.120.0_x64__8wekyb3d8bbwe"
"microsoft.windowscommunicationsapps_17.9330.21365.0_x64__8wekyb3d8bbwe"
"Microsoft.WindowsFeedbackHub_1.1805.2331.0_x64__8wekyb3d8bbwe"
"Microsoft.WindowsMaps_5.1805.1431.0_x64__8wekyb3d8bbwe"
#"Microsoft.WindowsSoundRecorder_10.1805.1941.0_x64__8wekyb3d8bbwe"
#"Microsoft.WindowsStore_11805.1001.49.0_x64__8wekyb3d8bbwe"
"Microsoft.Xbox.TCUI_1.11.28003.0_x64__8wekyb3d8bbwe"
"Microsoft.XboxApp_41.41.18001.0_x64__8wekyb3d8bbwe"
#"Microsoft.XboxGameCallableUI_1000.17763.1.0_neutral_neutral_cw5n1h2txyewy"
"Microsoft.XboxGameOverlay_1.32.17005.0_x64__8wekyb3d8bbwe"
"Microsoft.XboxGamingOverlay_2.20.22001.0_x64__8wekyb3d8bbwe"
"Microsoft.XboxIdentityProvider_12.44.20001.0_x64__8wekyb3d8bbwe"
"Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_x64__8wekyb3d8bbwe"
"Microsoft.YourPhone_0.0.12084.0_x64__8wekyb3d8bbwe"
"Microsoft.ZuneMusic_10.18052.20211.0_x64__8wekyb3d8bbwe"
"Microsoft.ZuneVideo_10.18052.20211.0_x64__8wekyb3d8bbwe"
#"Windows.CBSPreview_10.0.17763.1_neutral_neutral_cw5n1h2txyewy"
#"windows.immersivecontrolpanel_10.0.2.1000_neutral_neutral_cw5n1h2txyewy"
#"Windows.PrintDialog_6.2.1.0_neutral_neutral_cw5n1h2txyewy"
)
$appxpp = @(
"Microsoft.BingWeather_4.25.12127.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.DesktopAppInstaller_2018.720.2137.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.GetHelp_10.1706.10441.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.Getstarted_6.13.11581.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.HEIFImageExtension_1.0.11792.0_x64__8wekyb3d8bbwe"
"Microsoft.Messaging_2018.727.1430.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.Microsoft3DViewer_4.1808.15012.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.MicrosoftOfficeHub_2017.1219.520.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.MicrosoftSolitaireCollection_4.1.5252.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.MicrosoftStickyNotes_2.0.13.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.MixedReality.Portal_2000.18081.1242.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.MSPaint_4.1807.12027.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.Office.OneNote_16001.10228.20003.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.OneConnect_5.1807.1991.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.People_2018.516.2011.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.Print3D_3.0.1521.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.ScreenSketch_2018.731.48.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.SkypeApp_14.26.95.0_neutral_~_kzf8qxf38zg5c"
#"Microsoft.StorePurchaseApp_11805.1001.813.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.VP9VideoExtensions_1.0.12342.0_x64__8wekyb3d8bbwe"
"Microsoft.Wallet_2.2.18179.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WebMediaExtensions_1.0.12341.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WebpImageExtension_1.0.11551.0_x64__8wekyb3d8bbwe"
#"Microsoft.Windows.Photos_2018.18051.21218.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WindowsAlarms_2018.516.2059.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WindowsCalculator_2018.501.612.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WindowsCamera_2018.425.120.0_neutral_~_8wekyb3d8bbwe"
"microsoft.windowscommunicationsapps_2015.9330.21365.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.WindowsFeedbackHub_2018.822.2.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.WindowsMaps_2018.523.2143.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WindowsSoundRecorder_2018.713.2154.0_neutral_~_8wekyb3d8bbwe"
#"Microsoft.WindowsStore_11805.1001.4913.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.Xbox.TCUI_1.11.28003.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.XboxApp_41.41.18001.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.XboxGameOverlay_1.32.17005.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.XboxGamingOverlay_2.20.22001.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.XboxIdentityProvider_12.44.20001.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.YourPhone_2018.727.2137.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.ZuneMusic_2019.18052.20211.0_neutral_~_8wekyb3d8bbwe"
"Microsoft.ZuneVideo_2019.18052.20211.0_neutral_~_8wekyb3d8bbwe"
)
# This will use the above lists to remove the packages:
Get-AppxPackage -AllUsers | Where-Object { $appx -contains $PSItem.PackageFullName } | Remove-AppxPackage -AllUsers
Get-AppxProvisionedPackage -Online | Where-Object { $appxpp -contains $PSItem.PackageName } | Remove-AppxProvisionedPackage -Online -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'' and ''Uninstall'' it, and close the ''Settings'' 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 [[https://github.com/W4RH4WK/Debloat-Windows-10/blob/master/scripts/remove-onedrive.ps1|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'' and ''Taskbar'', and remove any Desktop shortcuts, except for ''Recycle 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 then ''Let 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 [[https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads|official]] and [[https://www.itechtics.com/microsoft-visual-c-redistributable-versions-direct-download-links/|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'' to ''C:\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
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 taskbar
- ''Off'' Automatically hide the taskbar in desktop mode
- ''Off'' Automatically hide the taskbar in tablet mode
- ''Off'' Use small taskbar buttons
- ''On'' Use Peek
- ''On'' Replace Command Prompt with Windows PowerShell
- ''On'' 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 Start
- ''On'' Show app list in Start menu
- ''Off'' Show recently added apps
- ''Off'' Show most used apps
- ''Off'' Use Start full screen
- ''On'' Show recently opened items in Jump Lists on Start or the taskbar
- ''Choose which folders appear on Start''
- ''On'' File Explorer
- ''On'' Settings
- ''On'' Documents
- ''On'' Downloads
- ''Off'' Music
- ''On'' Pictures
- ''Off'' Videos
- ''Off'' Network
- ''On'' 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 [[https://docs.microsoft.com/en-us/windows/configuration/windows-10-start-layout-options-and-policies|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:
- To import the layout do:Import-Startlayout -LayoutPath "\\MDT-Server\_prep\_startlayouts\layout.xml" -MountPath $env:SystemDrive\
- Because we're going to be using [[https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/customize-the-default-user-profile-by-using-copyprofile|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'' again
- ''Search Providers''
- Set ''Google'' as default and delete ''Bing''
- ''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'' and ''Connect''
- 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 again
- ''Disconnect'' and then switch to profile ''Gatorlink VPN'' and ''Connect''
- Click the ''Cisco AnyConnect'' icon in the system tray one last time
- ''Disconnect'' 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 '''' 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 settings
- ''Options -> 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'' under ''Advanced''
- ''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'' and ''Continue/Yes/Ok'' if any warnings come up
- If any errors about ''Edge'' come up, just terminate it via ''Task Manager'' and ''Run Cleaner'' again
- ''Run Cleaner'' a few times to confirm nothing is left over
- ''Registry -> 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 [[https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/customize-the-default-user-profile-by-using-copyprofile|copyprofile]], we need a prepared XML answer file to feed ''Sysprep''. Here is what that looks like:
true
To simplify executing ''Sysprep'' correctly, every time, I prepared the following batch file:
@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 ====
[[https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/customize-the-default-user-profile-by-using-copyprofile|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 the ''DVD Drive'' is at the top
- Perform the following in the shell:
rmdir /s /q "C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\"
rmdir /s /q "C:\Users\Administrator\AppData\Local\Microsoft\Windows\INetCache\"
rmdir /s /q "C:\Users\Administrator\AppData\Local\Microsoft\Windows\WebCache\"
rmdir /s /q "C:\Users\Administrator\AppData\Local\MicrosoftEdge\"
rmdir /s /q "C:\Users\Administrator\MicrosoftEdgeBackups\"
rmdir /s /q "C:\Users\Administrator\Favorites\"
rmdir /s /q "C:\Users\Administrator\.cisco\"
rmdir /s /q "C:\Users\Default\AppData\Local\Microsoft\WindowsApps\"
rmdir /s /q "C:\Users\Default\AppData\Local\Microsoft\Windows\INetCache\"
rmdir /s /q "C:\Users\Default\AppData\Local\Microsoft\Windows\WebCache\"
rmdir /s /q "C:\Users\Default\AppData\Local\MicrosoftEdge\"
rmdir /s /q "C:\Users\Default\MicrosoftEdgeBackups\"
rmdir /s /q "C:\Users\Default\Favorites\"
rmdir /s /q "C:\Users\Default\.cisco\"
rmdir /s /q "C:\Users\Public\"
del /q "C:\Users\Administrator\AppData\Local\Microsoft\Windows\WebCacheLock.dat"
del /q "C:\Users\Default\AppData\Local\Microsoft\Windows\WebCacheLock.dat"
- Stay in ''WinPE'' for [[#capture_phase_3_-_capture_the_wim|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
{{tag>computing osd}}