Compare commits

...

13 Commits

Author SHA1 Message Date
Chris Titus Tech
a8db21b2ef remove workflow change 2026-02-23 15:35:25 -06:00
Chris Titus Tech
787937d402 fix scroll to end 2026-02-23 15:22:15 -06:00
Chris Titus Tech
91ec6aca3b explain modify and creator button 2026-02-23 15:14:27 -06:00
Chris Titus Tech
02ba930b20 remove out-null and trailing whitespace 2026-02-23 15:12:44 -06:00
Chris Titus Tech
56bd18f2cd Cleanup 2026-02-23 15:06:21 -06:00
Chris Titus Tech
5c8adf3c9f update auto-merge 2026-02-23 14:27:40 -06:00
Chris Titus Tech
075bc0772c Keep step 4 output expanded 2026-02-23 14:16:13 -06:00
Chris Titus Tech
b315e6338a fix unapproved verb 2026-02-23 13:51:31 -06:00
Chris Titus Tech
c5b1cd027a Fix run for use 2026-02-23 13:46:44 -06:00
Chris Titus Tech
be85ecb2db remove old first startup 2026-02-23 13:28:20 -06:00
Chris Titus Tech
73fb487e58 fix startmenu on new 26h2 2026-02-23 13:27:47 -06:00
Chris Titus Tech
7abb4ae5fe cleanup and iso improvements 2026-02-23 12:36:32 -06:00
Chris Titus Tech
df75cd8c6f iso save success 2026-02-23 10:51:59 -06:00
5 changed files with 995 additions and 425 deletions

View File

@@ -14,6 +14,7 @@ function Write-Win11ISOLog {
} else {
$sync["WPFWin11ISOStatusLog"].Text += "`n[$timestamp] $Message"
}
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd()
})
}
@@ -98,10 +99,10 @@ function Invoke-WinUtilISOMountAndVerify {
# ── Read edition / architecture info ──
Set-WinUtilProgressBar -Label "Reading image metadata..." -Percent 55
$editions = Get-WindowsImage -ImagePath $activeWim | Select-Object -ExpandProperty ImageName
$imageInfo = Get-WindowsImage -ImagePath $activeWim | Select-Object ImageIndex, ImageName
# ── Verify at least one Win11 edition is present ──
$isWin11 = $editions | Where-Object { $_ -match "Windows 11" }
$isWin11 = $imageInfo | Where-Object { $_.ImageName -match "Windows 11" }
if (-not $isWin11) {
Dismount-DiskImage -ImagePath $isoPath | Out-Null
Write-Win11ISOLog "ERROR: No 'Windows 11' edition found in the image."
@@ -112,9 +113,20 @@ function Invoke-WinUtilISOMountAndVerify {
return
}
# Store edition info for later index lookup
$sync["Win11ISOImageInfo"] = $imageInfo
# ── Populate UI ──
$sync["WPFWin11ISOMountDriveLetter"].Text = "Mounted at: $driveLetter | Image file: $(Split-Path $activeWim -Leaf)"
$sync["WPFWin11ISOEditionList"].Text = ($editions -join "`n")
$sync["WPFWin11ISOEditionComboBox"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOEditionComboBox"].Items.Clear()
foreach ($img in $imageInfo) {
[void]$sync["WPFWin11ISOEditionComboBox"].Items.Add("$($img.ImageIndex): $($img.ImageName)")
}
if ($sync["WPFWin11ISOEditionComboBox"].Items.Count -gt 0) {
$sync["WPFWin11ISOEditionComboBox"].SelectedIndex = 0
}
})
$sync["WPFWin11ISOVerifyResultPanel"].Visibility = "Visible"
# Store for later steps
@@ -126,7 +138,7 @@ function Invoke-WinUtilISOMountAndVerify {
$sync["WPFWin11ISOModifySection"].Visibility = "Visible"
Set-WinUtilProgressBar -Label "ISO verified ✔" -Percent 100
Write-Win11ISOLog "ISO verified OK. Editions found: $($editions.Count)"
Write-Win11ISOLog "ISO verified OK. Editions found: $($imageInfo.Count)"
}
catch {
Write-Win11ISOLog "ERROR during mount/verify: $_"
@@ -162,21 +174,55 @@ function Invoke-WinUtilISOModify {
return
}
# ── Resolve selected edition index from the ComboBox ──
$selectedItem = $sync["WPFWin11ISOEditionComboBox"].SelectedItem
$selectedWimIndex = 1 # default fallback
if ($selectedItem -and $selectedItem -match '^(\d+):') {
$selectedWimIndex = [int]$Matches[1]
} elseif ($sync["Win11ISOImageInfo"]) {
$selectedWimIndex = $sync["Win11ISOImageInfo"][0].ImageIndex
}
$selectedEditionName = if ($selectedItem) { ($selectedItem -replace '^\d+:\s*', '') } else { "Unknown" }
Write-Win11ISOLog "Selected edition: $selectedEditionName (Index $selectedWimIndex)"
# Disable the modify button to prevent double-click
$sync["WPFWin11ISOModifyButton"].IsEnabled = $false
$workDir = Join-Path $env:TEMP "WinUtil_Win11ISO_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
$existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") -ErrorAction SilentlyContinue |
Where-Object { $_.PSIsContainer } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
$workDir = if ($existingWorkDir) {
Write-Win11ISOLog "Reusing existing temp directory: $($existingWorkDir.FullName)"
$existingWorkDir.FullName
} else {
Join-Path $env:TEMP "WinUtil_Win11ISO_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
}
# ── Resolve autounattend.xml content ──────────────────────────────────────
# Compiled winutil.ps1 sets $WinUtilAutounattendXml before main.ps1 runs.
# In dev/source mode fall back to reading tools\autounattend.xml directly.
$autounattendContent = if ($WinUtilAutounattendXml) {
$WinUtilAutounattendXml
} else {
$toolsXml = Join-Path $PSScriptRoot "..\..\tools\autounattend.xml"
if (Test-Path $toolsXml) { Get-Content $toolsXml -Raw } else { "" }
}
# ── Run modification in a background runspace ──
$runspace = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$runspace.ApartmentState = "STA"
$runspace.ThreadOptions = "ReuseThread"
$runspace.Open()
$runspace.SessionStateProxy.SetVariable("sync", $sync)
$runspace.SessionStateProxy.SetVariable("isoPath", $isoPath)
$runspace.SessionStateProxy.SetVariable("driveLetter", $driveLetter)
$runspace.SessionStateProxy.SetVariable("wimPath", $wimPath)
$runspace.SessionStateProxy.SetVariable("workDir", $workDir)
$runspace.SessionStateProxy.SetVariable("sync", $sync)
$runspace.SessionStateProxy.SetVariable("isoPath", $isoPath)
$runspace.SessionStateProxy.SetVariable("driveLetter", $driveLetter)
$runspace.SessionStateProxy.SetVariable("wimPath", $wimPath)
$runspace.SessionStateProxy.SetVariable("workDir", $workDir)
$runspace.SessionStateProxy.SetVariable("selectedWimIndex", $selectedWimIndex)
$runspace.SessionStateProxy.SetVariable("selectedEditionName", $selectedEditionName)
$runspace.SessionStateProxy.SetVariable("autounattendContent", $autounattendContent)
# Serialize functions so they are available inside the runspace
$isoScriptFuncDef = "function Invoke-WinUtilISOScript {`n" + `
@@ -204,6 +250,7 @@ function Invoke-WinUtilISOModify {
$ts = (Get-Date).ToString("HH:mm:ss")
$sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOStatusLog"].Text += "`n[$ts] $msg"
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd()
})
}
@@ -217,6 +264,27 @@ function Invoke-WinUtilISOModify {
}
try {
# ── Hide Steps 1-3 while modification is running; expand log to fill screen ──
$sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOSelectSection"].Visibility = "Collapsed"
$sync["WPFWin11ISOMountSection"].Visibility = "Collapsed"
$sync["WPFWin11ISOModifySection"].Visibility = "Collapsed"
$expandedHeight = [Math]::Max(400, $sync["Form"].ActualHeight - 100)
$sync["WPFWin11ISOStatusLog"].Height = $expandedHeight
$sync["Win11ISOLogExpanded"] = $true
# Register the resize handler once so the log tracks window resizes
if (-not $sync["Win11ISOResizeHandlerAdded"]) {
$sync["Form"].add_SizeChanged({
if ($sync["Win11ISOLogExpanded"]) {
$sync["WPFWin11ISOStatusLog"].Height = [Math]::Max(400, $sync["Form"].ActualHeight - 100)
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd()
}
})
$sync["Win11ISOResizeHandlerAdded"] = $true
}
})
# ── 1. Create working directory structure ──
Log "Creating working directory: $workDir"
$isoContents = Join-Path $workDir "iso_contents"
@@ -240,20 +308,47 @@ function Invoke-WinUtilISOModify {
# Ensure the file is writable
Set-ItemProperty -Path $localWim -Name IsReadOnly -Value $false
# ── 4. Mount the first index of install.wim ──
Log "Mounting install.wim (Index 1) at $mountDir..."
Mount-WindowsImage -ImagePath $localWim -Index 1 -Path $mountDir -ErrorAction Stop | Out-Null
# ── 4. Mount the selected edition of install.wim ──
Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..."
Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir -ErrorAction Stop | Out-Null
SetProgress "Modifying install.wim..." 45
# ── Apply all WinUtil modifications via Invoke-WinUtilISOScript ──
Log "Applying WinUtil modifications to install.wim..."
Invoke-WinUtilISOScript -ScratchDir $mountDir -Log { param($m) Log $m }
Invoke-WinUtilISOScript -ScratchDir $mountDir -ISOContentsDir $isoContents -AutoUnattendXml $autounattendContent -Log { param($m) Log $m }
# ── 4b. DISM component store cleanup ──
# /ResetBase removes all superseded component versions from WinSxS,
# which is the single largest space saving possible (typically 300800 MB).
# This must be done while the image is still mounted.
SetProgress "Cleaning up component store (WinSxS)..." 56
Log "Running DISM component store cleanup (/ResetBase)..."
& dism /English "/image:$mountDir" /Cleanup-Image /StartComponentCleanup /ResetBase | ForEach-Object { Log $_ }
Log "Component store cleanup complete."
# ── 5. Save and dismount the WIM ──
SetProgress "Saving modified install.wim..." 65
Log "Dismounting and saving install.wim..."
Log "Dismounting and saving install.wim. This will take several minutes..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null
Log "install.wim saved."
# ── 5b. Strip unused editions — export only the selected index ──
# A standard multi-edition install.wim can be 45 GB; exporting a
# single index typically drops it to ~3 GB, saving 12 GB in the ISO.
SetProgress "Removing unused editions from install.wim..." 70
Log "Exporting edition '$selectedEditionName' (Index $selectedWimIndex) to a single-edition install.wim..."
$exportWim = Join-Path $isoContents "sources\install_export.wim"
Export-WindowsImage `
-SourceImagePath $localWim `
-SourceIndex $selectedWimIndex `
-DestinationImagePath $exportWim `
-ErrorAction Stop | Out-Null
Remove-Item -Path $localWim -Force
Rename-Item -Path $exportWim -NewName "install.wim" -Force
# Update local path so later steps (e.g. ISO build) reference the new file
$localWim = Join-Path $isoContents "sources\install.wim"
Log "Unused editions removed. install.wim now contains only '$selectedEditionName'."
SetProgress "Dismounting source ISO..." 80
# ── 6. Dismount the original ISO ──
@@ -265,16 +360,54 @@ function Invoke-WinUtilISOModify {
$sync["Win11ISOContentsDir"] = $isoContents
SetProgress "Modification complete ✔" 100
Log "install.wim modification complete. Select an output option in Step 4."
Log "install.wim modification complete. Choose an output option in Step 4."
# ── Reveal Step 4 on the UI thread ──
# Note: USB drive enumeration (Get-Disk) is intentionally deferred to
# when the user explicitly selects the USB option, to avoid blocking
# the UI thread here.
$sync["WPFWin11ISOOutputSection"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOOutputSection"].Visibility = "Visible"
Invoke-WinUtilISORefreshUSBDrives
})
}
catch {
Log "ERROR during modification: $_"
# ── Cleanup: dismount WIM if still mounted ──
try {
if (Test-Path $mountDir) {
$mountedImages = Get-WindowsImage -Mounted -ErrorAction SilentlyContinue |
Where-Object { $_.Path -eq $mountDir }
if ($mountedImages) {
Log "Cleaning up: dismounting install.wim (discarding changes)..."
Dismount-WindowsImage -Path $mountDir -Discard -ErrorAction SilentlyContinue | Out-Null
}
}
} catch {
Log "Warning: could not dismount install.wim during cleanup: $_"
}
# ── Cleanup: dismount the source ISO ──
try {
$mountedISO = Get-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue
if ($mountedISO -and $mountedISO.Attached) {
Log "Cleaning up: dismounting source ISO..."
Dismount-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue | Out-Null
}
} catch {
Log "Warning: could not dismount ISO during cleanup: $_"
}
# ── Cleanup: remove temp working directory ──
try {
if (Test-Path $workDir) {
Log "Cleaning up: removing temp directory $workDir..."
Remove-Item -Path $workDir -Recurse -Force -ErrorAction SilentlyContinue
}
} catch {
Log "Warning: could not remove temp directory during cleanup: $_"
}
$sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{
[System.Windows.MessageBox]::Show(
"An error occurred during install.wim modification:`n`n$_",
@@ -288,6 +421,16 @@ function Invoke-WinUtilISOModify {
$sync.progressBarTextBlock.ToolTip = ""
$sync.ProgressBar.Value = 0
$sync["WPFWin11ISOModifyButton"].IsEnabled = $true
# ── Only restore steps 1-3 if Step 4 was NOT successfully shown ──
# When modification succeeds, Step 4 is visible and steps 1-3 stay
# hidden until the user clicks Clean & Reset.
if ($sync["WPFWin11ISOOutputSection"].Visibility -ne "Visible") {
$sync["WPFWin11ISOSelectSection"].Visibility = "Visible"
$sync["WPFWin11ISOMountSection"].Visibility = "Visible"
$sync["WPFWin11ISOModifySection"].Visibility = "Visible"
}
$sync["Win11ISOLogExpanded"] = $false
$sync["WPFWin11ISOStatusLog"].Height = 140
})
}
}) | Out-Null
@@ -295,6 +438,53 @@ function Invoke-WinUtilISOModify {
$script.BeginInvoke() | Out-Null
}
function Invoke-WinUtilISOCleanAndReset {
<#
.SYNOPSIS
Deletes the temporary working directory created during ISO modification
and resets the entire ISO UI back to its initial state (Step 1 only).
#>
$workDir = $sync["Win11ISOWorkDir"]
if ($workDir -and (Test-Path $workDir)) {
$confirm = [System.Windows.MessageBox]::Show(
"This will delete the temporary working directory:`n`n$workDir`n`nAnd reset the interface back to the start.`n`nContinue?",
"Clean & Reset", "YesNo", "Warning")
if ($confirm -ne "Yes") { return }
try {
Write-Win11ISOLog "Deleting temp directory: $workDir"
Remove-Item -Path $workDir -Recurse -Force -ErrorAction Stop
Write-Win11ISOLog "Temp directory deleted."
} catch {
Write-Win11ISOLog "WARNING: could not fully delete temp directory: $_"
}
}
# Clear all stored ISO state
$sync["Win11ISOWorkDir"] = $null
$sync["Win11ISOContentsDir"] = $null
$sync["Win11ISOImagePath"] = $null
$sync["Win11ISODriveLetter"] = $null
$sync["Win11ISOWimPath"] = $null
$sync["Win11ISOImageInfo"] = $null
$sync["Win11ISOUSBDisks"] = $null
# Reset the UI to the initial state
$sync["WPFWin11ISOPath"].Text = "No ISO selected..."
$sync["WPFWin11ISOFileInfo"].Visibility = "Collapsed"
$sync["WPFWin11ISOVerifyResultPanel"].Visibility = "Collapsed"
$sync["WPFWin11ISOOptionUSB"].Visibility = "Collapsed"
$sync["WPFWin11ISOOutputSection"].Visibility = "Collapsed"
$sync["WPFWin11ISOModifySection"].Visibility = "Collapsed"
$sync["WPFWin11ISOMountSection"].Visibility = "Collapsed"
$sync["WPFWin11ISOSelectSection"].Visibility = "Visible"
$sync["WPFWin11ISOStatusLog"].Text = "Ready. Please select a Windows 11 ISO to begin."
$sync["WPFWin11ISOStatusLog"].Height = 140
$sync["WPFWin11ISOModifyButton"].IsEnabled = $true
}
function Invoke-WinUtilISOExport {
<#
.SYNOPSIS
@@ -330,12 +520,28 @@ function Invoke-WinUtilISOExport {
Select-Object -First 1 -ExpandProperty FullName
if (-not $oscdimg) {
Set-WinUtilProgressBar -Label "" -Percent 0
Write-Win11ISOLog "oscdimg.exe not found. Install Windows ADK to enable ISO export."
[System.Windows.MessageBox]::Show(
"oscdimg.exe was not found.`n`nTo export an ISO you need the Windows Assessment and Deployment Kit (ADK).`n`nDownload it from: https://learn.microsoft.com/windows-hardware/get-started/adk-install",
"Windows ADK Required", "OK", "Warning")
return
Write-Win11ISOLog "oscdimg.exe not found. Attempting to install via winget..."
Set-WinUtilProgressBar -Label "Installing oscdimg..." -Percent 5
try {
$winget = Get-Command winget -ErrorAction Stop
$result = & $winget install -e --id Microsoft.OSCDIMG --accept-package-agreements --accept-source-agreements 2>&1
Write-Win11ISOLog "winget output: $result"
# Re-scan for oscdimg after install
$oscdimg = Get-ChildItem "C:\Program Files (x86)\Windows Kits" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty FullName
} catch {
Write-Win11ISOLog "winget not available or install failed: $_"
}
if (-not $oscdimg) {
Set-WinUtilProgressBar -Label "" -Percent 0
Write-Win11ISOLog "oscdimg.exe still not found after install attempt."
[System.Windows.MessageBox]::Show(
"oscdimg.exe could not be found or installed automatically.`n`nPlease install it manually:`n winget install -e --id Microsoft.OSCDIMG`n`nOr install the Windows ADK from:`nhttps://learn.microsoft.com/windows-hardware/get-started/adk-install",
"oscdimg Not Found", "OK", "Warning")
return
}
Write-Win11ISOLog "oscdimg.exe installed successfully."
}
# Build boot parameters (BIOS + UEFI dual-boot)
@@ -462,6 +668,7 @@ function Invoke-WinUtilISOWriteUSB {
$ts = (Get-Date).ToString("HH:mm:ss")
$sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOStatusLog"].Text += "`n[$ts] $msg"
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd()
})
}

View File

@@ -1,29 +1,65 @@
function Invoke-WinUtilISOScript {
<#
.SYNOPSIS
Applies the standard WinUtil modifications to a mounted Windows 11 install.wim image.
Applies WinUtil modifications to a mounted Windows 11 install.wim image.
.DESCRIPTION
Removes bloatware AppX packages, Edge, OneDrive, applies privacy/telemetry
registry tweaks, disables sponsored-app delivery, bypasses hardware checks,
copies autounattend.xml for local-account OOBE, and deletes unwanted
scheduled-task definition files — all against an already-mounted WIM image.
Performs the following operations against an already-mounted WIM image:
1. Removes provisioned AppX bloatware packages via DISM.
2. Deletes Microsoft Edge program files.
3. Removes OneDriveSetup.exe from the system image.
4. Loads offline registry hives (COMPONENTS, DEFAULT, NTUSER, SOFTWARE, SYSTEM)
and applies the following tweaks:
- Bypasses hardware requirement checks (CPU, RAM, SecureBoot, Storage, TPM).
- Disables sponsored-app delivery and ContentDeliveryManager features.
- Enables local-account OOBE path (BypassNRO).
- Writes autounattend.xml to the Sysprep directory inside the WIM and,
optionally, to the ISO/USB root so Windows Setup picks it up at boot.
- Disables reserved storage.
- Disables BitLocker device encryption.
- Hides the Chat (Teams) taskbar icon.
- Removes Edge uninstall registry entries.
- Disables OneDrive folder backup (KFM).
- Disables telemetry, advertising ID, and input personalization.
- Blocks post-install delivery of DevHome, Outlook, and Teams.
- Disables Windows Copilot.
- Disables Windows Update during OOBE.
5. Deletes unwanted scheduled-task XML definition files (CEIP, Appraiser, etc.).
6. Removes the support\ folder from the ISO contents directory (if supplied).
Mounting and dismounting the WIM is the responsibility of the caller
(e.g. Invoke-WinUtilISOModify).
(e.g. Invoke-WinUtilISO).
.PARAMETER ScratchDir
Full path to the directory where the Windows image is currently mounted
(the "scratchdir"). Example: C:\Temp\WinUtil_Win11ISO_20260222\wim_mount
Mandatory. Full path to the directory where the Windows image is currently mounted.
Example: C:\Users\USERNAME\AppData\Local\Temp\WinUtil_Win11ISO_20260222\wim_mount
.PARAMETER ISOContentsDir
Optional. Root directory of the extracted ISO contents.
When supplied, autounattend.xml is also written here so Windows Setup picks it
up automatically at boot, and the support\ folder is deleted from that location.
.PARAMETER AutoUnattendXml
Optional. Full XML content for autounattend.xml.
In compiled winutil.ps1 this is the embedded $WinUtilAutounattendXml here-string;
in dev mode it is read from tools\autounattend.xml.
If empty, the OOBE bypass file is skipped and a warning is logged.
.PARAMETER Log
Optional ScriptBlock used for progress/status logging.
Receives a single [string] message argument.
Defaults to Write-Output when not supplied.
Defaults to { param($m) Write-Output $m } when not supplied.
.EXAMPLE
Invoke-WinUtilISOScript -ScratchDir "C:\Temp\wim_mount"
Invoke-WinUtilISOScript -ScratchDir $mountDir -Log { param($m) Write-Host $m }
.EXAMPLE
Invoke-WinUtilISOScript `
-ScratchDir $mountDir `
-ISOContentsDir $isoRoot `
-AutoUnattendXml (Get-Content .\tools\autounattend.xml -Raw) `
-Log { param($m) Write-Host $m }
.NOTES
Author : Chris Titus @christitustech
@@ -32,6 +68,12 @@ function Invoke-WinUtilISOScript {
#>
param (
[Parameter(Mandatory)][string]$ScratchDir,
# Root directory of the extracted ISO contents. When supplied, autounattend.xml
# is written here so Windows Setup picks it up automatically at boot.
[string]$ISOContentsDir = "",
# Autounattend XML content. In compiled winutil.ps1 this comes from the embedded
# $WinUtilAutounattendXml here-string; in dev mode it is read from tools\autounattend.xml.
[string]$AutoUnattendXml = "",
[scriptblock]$Log = { param($m) Write-Output $m }
)
@@ -40,20 +82,20 @@ function Invoke-WinUtilISOScript {
$adminGroup = $adminSID.Translate([System.Security.Principal.NTAccount])
# ── Local helpers ─────────────────────────────────────────────────────────
function _ISOScript-SetReg {
function Set-ISOScriptReg {
param ([string]$path, [string]$name, [string]$type, [string]$value)
try {
& reg add $path /v $name /t $type /d $value /f | Out-Null
& reg add $path /v $name /t $type /d $value /f
& $Log "Set registry value: $path\$name"
} catch {
& $Log "Error setting registry value: $_"
}
}
function _ISOScript-DelReg {
function Remove-ISOScriptReg {
param ([string]$path)
try {
& reg delete $path /f | Out-Null
& reg delete $path /f
& $Log "Removed registry key: $path"
} catch {
& $Log "Error removing registry key: $_"
@@ -108,14 +150,12 @@ function Invoke-WinUtilISOScript {
'Microsoft.WindowsFeedbackHub',
'Microsoft.WindowsMaps',
'Microsoft.WindowsSoundRecorder',
'Microsoft.WindowsTerminal',
'Microsoft.ZuneMusic',
'Microsoft.ZuneVideo',
'MicrosoftCorporationII.MicrosoftFamily',
'MicrosoftCorporationII.QuickAssist',
'MSTeams',
'MicrosoftTeams',
'Microsoft.549981C3F5F10'
'MicrosoftTeams'
)
$packagesToRemove = $packages | Where-Object {
@@ -131,11 +171,6 @@ function Invoke-WinUtilISOScript {
# ═════════════════════════════════════════════════════════════════════════
& $Log "Removing Edge..."
Remove-Item -Path "$ScratchDir\Program Files (x86)\Microsoft\Edge" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$ScratchDir\Program Files (x86)\Microsoft\EdgeUpdate" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$ScratchDir\Program Files (x86)\Microsoft\EdgeCore" -Recurse -Force -ErrorAction SilentlyContinue
& takeown /f "$ScratchDir\Windows\System32\Microsoft-Edge-Webview" /r | Out-Null
& icacls "$ScratchDir\Windows\System32\Microsoft-Edge-Webview" /grant "$($adminGroup.Value):(F)" /T /C | Out-Null
Remove-Item -Path "$ScratchDir\Windows\System32\Microsoft-Edge-Webview" -Recurse -Force -ErrorAction SilentlyContinue
# ═════════════════════════════════════════════════════════════════════════
# 3. Remove OneDrive
@@ -149,109 +184,127 @@ function Invoke-WinUtilISOScript {
# 4. Registry tweaks
# ═════════════════════════════════════════════════════════════════════════
& $Log "Loading offline registry hives..."
reg load HKLM\zCOMPONENTS "$ScratchDir\Windows\System32\config\COMPONENTS" | Out-Null
reg load HKLM\zDEFAULT "$ScratchDir\Windows\System32\config\default" | Out-Null
reg load HKLM\zNTUSER "$ScratchDir\Users\Default\ntuser.dat" | Out-Null
reg load HKLM\zSOFTWARE "$ScratchDir\Windows\System32\config\SOFTWARE" | Out-Null
reg load HKLM\zSYSTEM "$ScratchDir\Windows\System32\config\SYSTEM" | Out-Null
reg load HKLM\zCOMPONENTS "$ScratchDir\Windows\System32\config\COMPONENTS"
reg load HKLM\zDEFAULT "$ScratchDir\Windows\System32\config\default"
reg load HKLM\zNTUSER "$ScratchDir\Users\Default\ntuser.dat"
reg load HKLM\zSOFTWARE "$ScratchDir\Windows\System32\config\SOFTWARE"
reg load HKLM\zSYSTEM "$ScratchDir\Windows\System32\config\SYSTEM"
& $Log "Bypassing system requirements..."
_ISOScript-SetReg 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassCPUCheck' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassRAMCheck' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassSecureBootCheck' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassStorageCheck' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassTPMCheck' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSYSTEM\Setup\MoSetup' 'AllowUpgradesWithUnsupportedTPMOrCPU' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassCPUCheck' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassRAMCheck' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassSecureBootCheck' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassStorageCheck' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassTPMCheck' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\Setup\MoSetup' 'AllowUpgradesWithUnsupportedTPMOrCPU' 'REG_DWORD' '1'
& $Log "Disabling sponsored apps..."
_ISOScript-SetReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'OemPreInstalledAppsEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'PreInstalledAppsEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SilentInstalledAppsEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableWindowsConsumerFeatures' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'ContentDeliveryAllowed' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\Start' 'ConfigureStartPins' 'REG_SZ' '{"pinnedList": [{}]}'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'FeatureManagementEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'PreInstalledAppsEverEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SoftLandingEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContentEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-310093Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338388Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338389Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338393Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-353694Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-353696Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SystemPaneSuggestionsEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\PushToInstall' 'DisablePushToInstall' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\MRT' 'DontOfferThroughWUAU' 'REG_DWORD' '1'
_ISOScript-DelReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Subscriptions'
_ISOScript-DelReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SuggestedApps'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableConsumerAccountStateContent' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableCloudOptimizedContent' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'OemPreInstalledAppsEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'PreInstalledAppsEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SilentInstalledAppsEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableWindowsConsumerFeatures' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'ContentDeliveryAllowed' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\Start' 'ConfigureStartPins' 'REG_SZ' '{"pinnedList": [{}]}'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'FeatureManagementEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'PreInstalledAppsEverEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SoftLandingEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContentEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-310093Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338388Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338389Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-338393Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-353694Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SubscribedContent-353696Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SystemPaneSuggestionsEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\PushToInstall' 'DisablePushToInstall' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\MRT' 'DontOfferThroughWUAU' 'REG_DWORD' '1'
Remove-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Subscriptions'
Remove-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SuggestedApps'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableConsumerAccountStateContent' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableCloudOptimizedContent' 'REG_DWORD' '1'
& $Log "Enabling local accounts on OOBE..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' 'BypassNRO' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' 'BypassNRO' 'REG_DWORD' '1'
$sysprepDest = "$ScratchDir\Windows\System32\Sysprep\autounattend.xml"
Set-Content -Path $sysprepDest -Value $WinUtilAutounattendXml -Encoding UTF8 -Force
& $Log "Written autounattend.xml to Sysprep directory."
if ($AutoUnattendXml) {
# ── Place autounattend.xml inside the WIM (Sysprep) ──────────────────
$sysprepDest = "$ScratchDir\Windows\System32\Sysprep\autounattend.xml"
Set-Content -Path $sysprepDest -Value $AutoUnattendXml -Encoding UTF8 -Force
& $Log "Written autounattend.xml to Sysprep directory."
# ── Place autounattend.xml at the ISO / USB root ──────────────────────
# Windows Setup reads this file first (before booting into the OS),
# which is what drives the local-account / OOBE bypass at install time.
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
$isoDest = Join-Path $ISOContentsDir "autounattend.xml"
Set-Content -Path $isoDest -Value $AutoUnattendXml -Encoding UTF8 -Force
& $Log "Written autounattend.xml to ISO root ($isoDest)."
}
} else {
& $Log "Warning: autounattend.xml content is empty — skipping OOBE bypass file."
}
& $Log "Disabling reserved storage..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager' 'ShippedWithReserves' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager' 'ShippedWithReserves' 'REG_DWORD' '0'
& $Log "Disabling BitLocker device encryption..."
_ISOScript-SetReg 'HKLM\zSYSTEM\ControlSet001\Control\BitLocker' 'PreventDeviceEncryption' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSYSTEM\ControlSet001\Control\BitLocker' 'PreventDeviceEncryption' 'REG_DWORD' '1'
& $Log "Disabling Chat icon..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat' 'ChatIcon' 'REG_DWORD' '3'
_ISOScript-SetReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'TaskbarMn' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat' 'ChatIcon' 'REG_DWORD' '3'
Set-ISOScriptReg 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'TaskbarMn' 'REG_DWORD' '0'
& $Log "Removing Edge registry entries..."
_ISOScript-DelReg 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge'
_ISOScript-DelReg 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update'
Remove-ISOScriptReg 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge'
Remove-ISOScriptReg 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update'
& $Log "Disabling OneDrive folder backup..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\OneDrive' 'DisableFileSyncNGSC' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\OneDrive' 'DisableFileSyncNGSC' 'REG_DWORD' '1'
& $Log "Disabling telemetry..."
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo' 'Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Privacy' 'TailoredExperiencesWithDiagnosticDataEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Speech_OneCore\Settings\OnlineSpeechPrivacy' 'HasAccepted' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Input\TIPC' 'Enabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' 'RestrictImplicitInkCollection' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' 'RestrictImplicitTextCollection' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization\TrainedDataStore' 'HarvestContacts' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zNTUSER\Software\Microsoft\Personalization\Settings' 'AcceptedPrivacyPolicy' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' 'AllowTelemetry' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' 'Start' 'REG_DWORD' '4'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo' 'Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Privacy' 'TailoredExperiencesWithDiagnosticDataEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Speech_OneCore\Settings\OnlineSpeechPrivacy' 'HasAccepted' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Input\TIPC' 'Enabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' 'RestrictImplicitInkCollection' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' 'RestrictImplicitTextCollection' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization\TrainedDataStore' 'HarvestContacts' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zNTUSER\Software\Microsoft\Personalization\Settings' 'AcceptedPrivacyPolicy' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' 'AllowTelemetry' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' 'Start' 'REG_DWORD' '4'
& $Log "Preventing installation of DevHome and Outlook..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\DevHomeUpdate' 'workCompleted' 'REG_DWORD' '1'
_ISOScript-DelReg 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate'
_ISOScript-DelReg 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\DevHomeUpdate' 'workCompleted' 'REG_DWORD' '1'
Remove-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate'
Remove-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate'
& $Log "Disabling Copilot..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsCopilot' 'TurnOffWindowsCopilot' 'REG_DWORD' '1'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Edge' 'HubsSidebarEnabled' 'REG_DWORD' '0'
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Explorer' 'DisableSearchBoxSuggestions' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsCopilot' 'TurnOffWindowsCopilot' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Edge' 'HubsSidebarEnabled' 'REG_DWORD' '0'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Explorer' 'DisableSearchBoxSuggestions' 'REG_DWORD' '1'
& $Log "Disabling Windows Update during OOBE (re-enabled on first logon via FirstLogon.ps1)..."
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' 'NoAutoUpdate' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' 'DisableWindowsUpdateAccess' 'REG_DWORD' '1'
& $Log "Preventing installation of Teams..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Teams' 'DisableInstallation' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Teams' 'DisableInstallation' 'REG_DWORD' '1'
& $Log "Preventing installation of new Outlook..."
_ISOScript-SetReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Mail' 'PreventRun' 'REG_DWORD' '1'
Set-ISOScriptReg 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Mail' 'PreventRun' 'REG_DWORD' '1'
& $Log "Unloading offline registry hives..."
reg unload HKLM\zCOMPONENTS | Out-Null
reg unload HKLM\zDEFAULT | Out-Null
reg unload HKLM\zNTUSER | Out-Null
reg unload HKLM\zSOFTWARE | Out-Null
reg unload HKLM\zSYSTEM | Out-Null
reg unload HKLM\zCOMPONENTS
reg unload HKLM\zDEFAULT
reg unload HKLM\zNTUSER
reg unload HKLM\zSOFTWARE
reg unload HKLM\zSYSTEM
# ═════════════════════════════════════════════════════════════════════════
# 5. Delete scheduled task definition files
@@ -266,5 +319,13 @@ function Invoke-WinUtilISOScript {
Remove-Item "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force -ErrorAction SilentlyContinue
& $Log "Scheduled task files deleted."
}
# ═════════════════════════════════════════════════════════════════════════
# 6. Remove ISO support folder (fresh-install only; not needed)
# ═════════════════════════════════════════════════════════════════════════
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
& $Log "Removing ISO support\ folder..."
Remove-Item -Path (Join-Path $ISOContentsDir "support") -Recurse -Force -ErrorAction SilentlyContinue
& $Log "ISO support\ folder removed."
}
}

View File

@@ -554,11 +554,18 @@ $sync["WPFWin11ISOModifyButton"].Add_Click({
Invoke-WinUtilISOModify
})
$sync["WPFWin11ISOExportButton"].Add_Click({
Write-Debug "WPFWin11ISOExportButton clicked"
$sync["WPFWin11ISOChooseISOButton"].Add_Click({
Write-Debug "WPFWin11ISOChooseISOButton clicked"
$sync["WPFWin11ISOOptionUSB"].Visibility = "Collapsed"
Invoke-WinUtilISOExport
})
$sync["WPFWin11ISOChooseUSBButton"].Add_Click({
Write-Debug "WPFWin11ISOChooseUSBButton clicked"
$sync["WPFWin11ISOOptionUSB"].Visibility = "Visible"
Invoke-WinUtilISORefreshUSBDrives
})
$sync["WPFWin11ISORefreshUSBButton"].Add_Click({
Write-Debug "WPFWin11ISORefreshUSBButton clicked"
Invoke-WinUtilISORefreshUSBDrives
@@ -569,6 +576,11 @@ $sync["WPFWin11ISOWriteUSBButton"].Add_Click({
Invoke-WinUtilISOWriteUSB
})
$sync["WPFWin11ISOCleanResetButton"].Add_Click({
Write-Debug "WPFWin11ISOCleanResetButton clicked"
Invoke-WinUtilISOCleanAndReset
})
# ──────────────────────────────────────────────────────────────────────────────
$sync["Form"].ShowDialog() | out-null

View File

@@ -1,239 +1,507 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Windows 11 Unattended Installation Answer File
================================================
UNIVERSAL — no modification required before use.
What this file does automatically:
• Installs "Windows 11 Pro" from any standard Microsoft ISO
• Bypasses the Microsoft-account OOBE requirement (local account)
• Skips the EULA, wireless, and privacy nag screens
• Leaves timezone, language, region, and user account to the user
at the two short OOBE screens that remain
What the user is prompted for during first-run (OOBE):
1. Region / Language / Keyboard (one screen)
2. Who will use this PC? (local account name + password)
Timezone is set to UTC and can be adjusted after login.
Computer name is auto-generated; rename at any time.
Tested against: Windows 11 Home / Pro / Home Single Language (amd64)
Pass order: windowsPE → specialize → oobeSystem
-->
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<!-- ═══════════════════════════════════════════════════════════════════
PASS 1 — windowsPE
Runs inside the installer environment before the OS is laid down.
Handles disk layout and image selection only.
Locale is intentionally omitted so the installer inherits the
language of whichever ISO is being used.
═══════════════════════════════════════════════════════════════════════ -->
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<!--https://schneegans.de/windows/unattend-generator/?LanguageMode=Interactive&ProcessorArchitecture=amd64&BypassRequirementsCheck=true&ComputerNameMode=Random&CompactOsMode=Default&TimeZoneMode=Implicit&PartitionMode=Interactive&DiskAssertionMode=Skip&WindowsEditionMode=Interactive&InstallFromMode=Automatic&PEMode=Default&UserAccountMode=InteractiveLocal&PasswordExpirationMode=Unlimited&LockoutMode=Default&HideFiles=Hidden&ClassicContextMenu=true&LaunchToThisPC=true&ShowEndTask=true&TaskbarSearch=Hide&TaskbarIconsMode=Empty&DisableWidgets=true&LeftTaskbar=true&HideTaskViewButton=true&StartTilesMode=Default&StartPinsMode=Empty&EnableLongPaths=true&HideEdgeFre=true&DisableEdgeStartupBoost=true&DeleteWindowsOld=true&EffectsMode=Default&DeleteEdgeDesktopIcon=true&DesktopIconsMode=Default&StartFoldersMode=Default&WifiMode=Skip&ExpressSettings=DisableAll&LockKeysMode=Configure&CapsLockInitial=Off&CapsLockBehavior=Toggle&NumLockInitial=On&NumLockBehavior=Toggle&ScrollLockInitial=Off&ScrollLockBehavior=Toggle&StickyKeysMode=Disabled&ColorMode=Custom&SystemColorTheme=Dark&AppsColorTheme=Dark&AccentColor=%230078d4&WallpaperMode=Default&LockScreenMode=Default&WdacMode=Skip&AppLockerMode=Skip-->
<settings pass="offlineServicing"></settings>
<settings pass="windowsPE">
<!-- Setup / image selection -->
<component name="Microsoft-Windows-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">
<!-- Disable dynamic updates during setup (keeps installation offline/fast) -->
<DynamicUpdate>
<Enable>false</Enable>
</DynamicUpdate>
<ImageInstall>
<OSImage>
<!-- CompactOS saves ~1.5 GB but is slower on spinning drives -->
<Compact>false</Compact>
<WillShowUI>OnError</WillShowUI>
<InstallFrom>
<!--
Select the edition by NAME rather than by index number.
Index numbers vary between ISO builds; the name is stable.
Change "Windows 11 Pro" to "Windows 11 Home" etc. if your
ISO only contains that edition. To choose interactively,
delete this entire <InstallFrom> block.
-->
<MetaData wcm:action="add">
<Key>/IMAGE/NAME</Key>
<Value>Windows 11 Pro</Value>
</MetaData>
</InstallFrom>
<!-- InstallTo is omitted — the Windows installer will prompt
the user to select the destination disk and partition. -->
</OSImage>
</ImageInstall>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserData>
<AcceptEula>true</AcceptEula>
<ProductKey>
<!--
Leave <Key> absent to use an existing digital licence or
to be prompted for one after setup.
Generic setup keys (allow setup to proceed; do NOT activate):
Home : YTMG3-N6DKC-DKB77-7M9GH-8HVX7
Home Single Language : 7HNRX-D7KGG-3K4RQ-4WPJ4-YTDFH
Pro : VK7JG-NPHTM-C97JM-9MPGT-3V66T
Education : YNMGQ-8RYV3-4PGQ3-C8XTP-7CFBY
Enterprise : XGVPP-NMH47-7TTHJ-W3FW7-8HV2C
-->
<WillShowUI>OnError</WillShowUI>
<Key>00000-00000-00000-00000-00000</Key>
<WillShowUI>Always</WillShowUI>
</ProductKey>
<AcceptEula>true</AcceptEula>
</UserData>
<UseConfigurationSet>false</UseConfigurationSet>
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<!-- ═══════════════════════════════════════════════════════════════════
PASS 2 — specialize
First boot into the installed OS.
Machine-level settings that do not vary by user or region.
═══════════════════════════════════════════════════════════════════════ -->
<settings pass="generalize"></settings>
<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">
<!-- Auto-generate a unique computer name. Rename anytime:
Settings System About Rename this PC -->
<ComputerName>*</ComputerName>
<!--
UTC is the only timezone that is correct everywhere on Earth
without knowing where the machine will be used.
Windows will auto-adjust to local time once the user sets their
region, or they can change it in Settings Time & Language.
-->
<TimeZone>UTC</TimeZone>
<!-- Suppress the Teams/Chat auto-install prompt during setup -->
<ConfigureChatAutoInstall>false</ConfigureChatAutoInstall>
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>powershell.exe -WindowStyle "Normal" -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>powershell.exe -WindowStyle "Normal" -ExecutionPolicy "Unrestricted" -NoProfile -File "C:\Windows\Setup\Scripts\Specialize.ps1"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>powershell.exe -WindowStyle "Normal" -ExecutionPolicy "Unrestricted" -NoProfile -File "C:\Windows\Setup\Scripts\DefaultUser.ps1"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>reg.exe unload "HKU\DefaultUser"</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
<!-- Reduce telemetry to the minimum permitted by the licence.
0 = Security (Enterprise/Education only; treated as 1 on other SKUs)
1 = Basic / Required diagnostic data ← effective minimum for Home/Pro -->
<component name="Microsoft-Windows-SQMAPI"
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">
<CEIPEnabled>0</CEIPEnabled>
</component>
</settings>
<!-- ═══════════════════════════════════════════════════════════════════
PASS 3 — oobeSystem
Out-of-Box Experience (first-run wizard).
Screens shown to the user (everything else is suppressed):
① Region / Language / Keyboard layout — user picks their locale
② Create a local account — user picks name + password
Screens suppressed automatically:
• EULA
• "Sign in with Microsoft" / online account
• Wi-Fi selection (can be done after login)
• "Let Microsoft and apps use your location", Cortana, etc.
Locale settings are intentionally omitted here so that Windows
applies whatever the user selects on screen ①.
═══════════════════════════════════════════════════════════════════════ -->
<settings pass="auditSystem"></settings>
<settings pass="auditUser"></settings>
<settings pass="oobeSystem">
<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">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<OOBE>
<!-- Suppress the licence agreement — already accepted in windowsPE -->
<HideEULAPage>true</HideEULAPage>
<!-- KEEP false — this is the screen where the user creates -->
<!-- their local account (name + password). Setting it true -->
<!-- would skip account creation entirely, leaving only the -->
<!-- built-in Administrator account. -->
<HideLocalAccountScreen>false</HideLocalAccountScreen>
<!-- Suppress "Sign in with Microsoft" screens.
The user goes straight to local account creation. -->
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<!-- Skip Wi-Fi setup — can be connected after first login -->
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<!-- Suppress the privacy / recommended-settings nag screen -->
<ProtectYourPC>3</ProtectYourPC>
<HideEULAPage>true</HideEULAPage>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
</OOBE>
<!--
UserAccounts and AutoLogon are intentionally absent.
The user creates their own account on the OOBE screen above.
This is the safest and most universally applicable approach:
no hardcoded credentials ship inside the answer file.
If you want to pre-create an account instead, add:
<UserAccounts>
<LocalAccounts>
<LocalAccount wcm:action="add">
<Name>YourUsername</Name>
<Password>
<Value>YourPassword</Value>
<PlainText>true</PlainText>
</Password>
<DisplayName>Your Full Name</DisplayName>
<Group>Administrators</Group>
</LocalAccount>
</LocalAccounts>
</UserAccounts>
<AutoLogon>
<Enabled>true</Enabled>
<LogonCount>1</LogonCount>
<Username>YourUsername</Username>
<Password>
<Value>YourPassword</Value>
<PlainText>true</PlainText>
</Password>
</AutoLogon>
And set HideLocalAccountScreen to true above.
-->
<!--
Optional: run a script on first logon.
Uncomment and adjust the path/command as needed.
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://christitus.com/win | iex"</CommandLine>
<Description>Launch WinUtil post-install</Description>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
</FirstLogonCommands>
-->
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>powershell.exe -WindowStyle "Normal" -ExecutionPolicy "Unrestricted" -NoProfile -File "C:\Windows\Setup\Scripts\FirstLogon.ps1"</CommandLine>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
<Extensions xmlns="https://schneegans.de/windows/unattend-generator/">
<ExtractScript>
param(
[xml]$Document
);
foreach( $file in $Document.unattend.Extensions.File ) {
$path = [System.Environment]::ExpandEnvironmentVariables( $file.GetAttribute( 'path' ) );
mkdir -Path( $path | Split-Path -Parent ) -ErrorAction 'SilentlyContinue';
$encoding = switch( [System.IO.Path]::GetExtension( $path ) ) {
{ $_ -in '.ps1', '.xml' } { [System.Text.Encoding]::UTF8; }
{ $_ -in '.reg', '.vbs', '.js' } { [System.Text.UnicodeEncoding]::new( $false, $true ); }
default { [System.Text.Encoding]::Default; }
};
$bytes = $encoding.GetPreamble() + $encoding.GetBytes( $file.InnerText.Trim() );
[System.IO.File]::WriteAllBytes( $path, $bytes );
}
</ExtractScript>
<File path="C:\Windows\Setup\Scripts\TaskbarLayoutModification.xml">
&lt;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"&gt;
&lt;CustomTaskbarLayoutCollection PinListPlacement="Replace"&gt;
&lt;defaultlayout:TaskbarLayout&gt;
&lt;taskbar:TaskbarPinList&gt;
&lt;taskbar:DesktopApp DesktopApplicationLinkPath="#leaveempty" /&gt;
&lt;/taskbar:TaskbarPinList&gt;
&lt;/defaultlayout:TaskbarLayout&gt;
&lt;/CustomTaskbarLayoutCollection&gt;
&lt;/LayoutModificationTemplate&gt;
</File>
<File path="C:\Windows\Setup\Scripts\UnlockStartLayout.vbs">
HKU = &amp;H80000003
Set reg = GetObject("winmgmts://./root/default:StdRegProv")
Set fso = CreateObject("Scripting.FileSystemObject")
If reg.EnumKey(HKU, "", sids) = 0 Then
If Not IsNull(sids) Then
For Each sid In sids
key = sid + "\Software\Policies\Microsoft\Windows\Explorer"
name = "LockedStartLayout"
If reg.GetDWORDValue(HKU, key, name, existing) = 0 Then
reg.SetDWORDValue HKU, key, name, 0
End If
Next
End If
End If
</File>
<File path="C:\Windows\Setup\Scripts\UnlockStartLayout.xml">
&lt;Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"&gt;
&lt;Triggers&gt;
&lt;EventTrigger&gt;
&lt;Enabled&gt;true&lt;/Enabled&gt;
&lt;Subscription&gt;&amp;lt;QueryList&amp;gt;&amp;lt;Query Id="0" Path="Application"&amp;gt;&amp;lt;Select Path="Application"&amp;gt;*[System[Provider[@Name='UnattendGenerator'] and EventID=1]]&amp;lt;/Select&amp;gt;&amp;lt;/Query&amp;gt;&amp;lt;/QueryList&amp;gt;&lt;/Subscription&gt;
&lt;/EventTrigger&gt;
&lt;/Triggers&gt;
&lt;Principals&gt;
&lt;Principal id="Author"&gt;
&lt;UserId&gt;S-1-5-18&lt;/UserId&gt;
&lt;RunLevel&gt;LeastPrivilege&lt;/RunLevel&gt;
&lt;/Principal&gt;
&lt;/Principals&gt;
&lt;Settings&gt;
&lt;MultipleInstancesPolicy&gt;IgnoreNew&lt;/MultipleInstancesPolicy&gt;
&lt;DisallowStartIfOnBatteries&gt;false&lt;/DisallowStartIfOnBatteries&gt;
&lt;StopIfGoingOnBatteries&gt;false&lt;/StopIfGoingOnBatteries&gt;
&lt;AllowHardTerminate&gt;true&lt;/AllowHardTerminate&gt;
&lt;StartWhenAvailable&gt;false&lt;/StartWhenAvailable&gt;
&lt;RunOnlyIfNetworkAvailable&gt;false&lt;/RunOnlyIfNetworkAvailable&gt;
&lt;IdleSettings&gt;
&lt;StopOnIdleEnd&gt;true&lt;/StopOnIdleEnd&gt;
&lt;RestartOnIdle&gt;false&lt;/RestartOnIdle&gt;
&lt;/IdleSettings&gt;
&lt;AllowStartOnDemand&gt;true&lt;/AllowStartOnDemand&gt;
&lt;Enabled&gt;true&lt;/Enabled&gt;
&lt;Hidden&gt;false&lt;/Hidden&gt;
&lt;RunOnlyIfIdle&gt;false&lt;/RunOnlyIfIdle&gt;
&lt;WakeToRun&gt;false&lt;/WakeToRun&gt;
&lt;ExecutionTimeLimit&gt;PT72H&lt;/ExecutionTimeLimit&gt;
&lt;Priority&gt;7&lt;/Priority&gt;
&lt;/Settings&gt;
&lt;Actions Context="Author"&gt;
&lt;Exec&gt;
&lt;Command&gt;C:\Windows\System32\wscript.exe&lt;/Command&gt;
&lt;Arguments&gt;C:\Windows\Setup\Scripts\UnlockStartLayout.vbs&lt;/Arguments&gt;
&lt;/Exec&gt;
&lt;/Actions&gt;
&lt;/Task&gt;
</File>
<File path="C:\Windows\Setup\Scripts\SetStartPins.ps1">
$json = '{"pinnedList":[]}';
if( [System.Environment]::OSVersion.Version.Build -lt 20000 ) {
return;
}
$key = 'Registry::HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start';
New-Item -Path $key -ItemType 'Directory' -ErrorAction 'SilentlyContinue';
Set-ItemProperty -LiteralPath $key -Name 'ConfigureStartPins' -Value $json -Type 'String';
</File>
<File path="C:\Windows\Setup\Scripts\SetColorTheme.ps1">
$lightThemeSystem = 0;
$lightThemeApps = 0;
$accentColorOnStart = 0;
$enableTransparency = 0;
$htmlAccentColor = '#0078D4';
&amp; {
$params = @{
LiteralPath = 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize';
Force = $true;
Type = 'DWord';
};
Set-ItemProperty @params -Name 'SystemUsesLightTheme' -Value $lightThemeSystem;
Set-ItemProperty @params -Name 'AppsUseLightTheme' -Value $lightThemeApps;
Set-ItemProperty @params -Name 'ColorPrevalence' -Value $accentColorOnStart;
Set-ItemProperty @params -Name 'EnableTransparency' -Value $enableTransparency;
};
&amp; {
Add-Type -AssemblyName 'System.Drawing';
$accentColor = [System.Drawing.ColorTranslator]::FromHtml( $htmlAccentColor );
function ConvertTo-DWord {
param(
[System.Drawing.Color]
$Color
);
[byte[]]$bytes = @(
$Color.R;
$Color.G;
$Color.B;
$Color.A;
);
return [System.BitConverter]::ToUInt32( $bytes, 0);
}
$startColor = [System.Drawing.Color]::FromArgb( 0xD2, $accentColor );
Set-ItemProperty -LiteralPath 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Accent' -Name 'StartColorMenu' -Value( ConvertTo-DWord -Color $accentColor ) -Type 'DWord' -Force;
Set-ItemProperty -LiteralPath 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Accent' -Name 'AccentColorMenu' -Value( ConvertTo-DWord -Color $accentColor ) -Type 'DWord' -Force;
Set-ItemProperty -LiteralPath 'Registry::HKCU\Software\Microsoft\Windows\DWM' -Name 'AccentColor' -Value( ConvertTo-DWord -Color $accentColor ) -Type 'DWord' -Force;
$params = @{
LiteralPath = 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Accent';
Name = 'AccentPalette';
};
$palette = Get-ItemPropertyValue @params;
$index = 20;
$palette[ $index++ ] = $accentColor.R;
$palette[ $index++ ] = $accentColor.G;
$palette[ $index++ ] = $accentColor.B;
$palette[ $index++ ] = $accentColor.A;
Set-ItemProperty @params -Value $palette -Type 'Binary' -Force;
};
</File>
<File path="C:\Windows\Setup\Scripts\Specialize.ps1">
$scripts = @(
{
reg.exe add "HKLM\SYSTEM\Setup\MoSetup" /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f;
};
{
net.exe accounts /maxpwage:UNLIMITED;
};
{
reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableCloudOptimizedContent" /t REG_DWORD /d 1 /f;
[System.Diagnostics.EventLog]::CreateEventSource( 'UnattendGenerator', 'Application' );
};
{
Register-ScheduledTask -TaskName 'UnlockStartLayout' -Xml $( Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\UnlockStartLayout.xml' -Raw );
};
{
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f
};
{
Remove-Item -LiteralPath 'C:\Users\Public\Desktop\Microsoft Edge.lnk' -ErrorAction 'SilentlyContinue' -Verbose;
};
{
reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Dsh" /v AllowNewsAndInterests /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKLM\Software\Policies\Microsoft\Edge" /v HideFirstRunExperience /t REG_DWORD /d 1 /f;
};
{
reg.exe add "HKLM\Software\Policies\Microsoft\Edge\Recommended" /v BackgroundModeEnabled /t REG_DWORD /d 0 /f;
reg.exe add "HKLM\Software\Policies\Microsoft\Edge\Recommended" /v StartupBoostEnabled /t REG_DWORD /d 0 /f;
};
{
&amp; 'C:\Windows\Setup\Scripts\SetStartPins.ps1';
};
{
reg.exe add "HKU\.DEFAULT\Control Panel\Accessibility\StickyKeys" /v Flags /t REG_SZ /d 10 /f;
};
{
reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v NoAutoUpdate /t REG_DWORD /d 1 /f;
reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v DisableWindowsUpdateAccess /t REG_DWORD /d 1 /f;
};
);
&amp; {
[float]$complete = 0;
[float]$increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Id 0 -Activity 'Running scripts to customize your Windows installation. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 | Out-String -Width 1KB -Stream &gt;&gt; "C:\Windows\Setup\Scripts\Specialize.log";
</File>
<File path="C:\Windows\Setup\Scripts\UserOnce.ps1">
$scripts = @(
{
[System.Diagnostics.EventLog]::WriteEntry( 'UnattendGenerator', "User '$env:USERNAME' has requested to unlock the Start menu layout.", [System.Diagnostics.EventLogEntryType]::Information, 1 );
};
{
Remove-Item -Path "${env:USERPROFILE}\Desktop\*.lnk" -Force -ErrorAction 'SilentlyContinue';
Remove-Item -Path "$env:HOMEDRIVE\Users\Default\Desktop\*.lnk" -Force -ErrorAction 'SilentlyContinue';
};
{
$taskbarPath = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar";
if( Test-Path $taskbarPath ) {
Get-ChildItem -Path $taskbarPath -File | Remove-Item -Force;
}
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Name 'FavoritesRemovedChanges' -Force -ErrorAction 'SilentlyContinue';
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Name 'FavoritesChanges' -Force -ErrorAction 'SilentlyContinue';
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Name 'Favorites' -Force -ErrorAction 'SilentlyContinue';
};
{
reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /ve /f;
};
{
Set-ItemProperty -LiteralPath 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'LaunchTo' -Type 'DWord' -Value 1;
};
{
Set-ItemProperty -LiteralPath 'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Search' -Name 'SearchboxTaskbarMode' -Type 'DWord' -Value 0;
};
{
&amp; 'C:\Windows\Setup\Scripts\SetColorTheme.ps1';
};
{
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /v Enabled /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /v Enabled /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /v Enabled /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.AccountHealth" /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.AccountHealth" /v Enabled /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Start" /v AllAppsViewMode /t REG_DWORD /d 2 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v Start_IrisRecommendations /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v Start_AccountNotifications /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Start" /v ShowAllPinsList /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Start" /v ShowFrequentList /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Start" /v ShowRecentList /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v Start_TrackDocs /t REG_DWORD /d 0 /f;
};
{
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class Win32Broadcast {
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
IntPtr wParam,
string lParam,
uint fuFlags,
uint uTimeout,
out IntPtr lpdwResult);
}
"@;
[Win32Broadcast]::SendMessageTimeout( [IntPtr]0xffff, 0x1A, [IntPtr]::Zero, 'ImmersiveColorSet', 0x2, 100, [ref]([IntPtr]::Zero) );
};
{
Get-Process -Name 'explorer' -ErrorAction 'SilentlyContinue' | Where-Object -FilterScript {
$_.SessionId -eq ( Get-Process -Id $PID ).SessionId;
} | Stop-Process -Force;
};
);
&amp; {
[float]$complete = 0;
[float]$increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Id 0 -Activity 'Running scripts to configure this user account. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 | Out-String -Width 1KB -Stream &gt;&gt; "$env:TEMP\UserOnce.log";
</File>
<File path="C:\Windows\Setup\Scripts\DefaultUser.ps1">
$scripts = @(
{
reg.exe add "HKU\DefaultUser\Software\Policies\Microsoft\Windows\Explorer" /v "StartLayoutFile" /t REG_SZ /d "C:\Windows\Setup\Scripts\TaskbarLayoutModification.xml" /f;
reg.exe add "HKU\DefaultUser\Software\Policies\Microsoft\Windows\Explorer" /v "LockedStartLayout" /t REG_DWORD /d 1 /f;
};
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v ShowTaskViewButton /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v TaskbarAl /t REG_DWORD /d 0 /f;
};
{
foreach( $root in 'Registry::HKU\.DEFAULT', 'Registry::HKU\DefaultUser' ) {
Set-ItemProperty -LiteralPath "$root\Control Panel\Keyboard" -Name 'InitialKeyboardIndicators' -Type 'String' -Value 2 -Force;
}
};
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarDeveloperSettings" /v TaskbarEndTask /t REG_DWORD /d 1 /f;
};
{
reg.exe add "HKU\DefaultUser\Control Panel\Accessibility\StickyKeys" /v Flags /t REG_SZ /d 10 /f;
};
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\DWM" /v ColorPrevalence /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\RunOnce" /v "UnattendedSetup" /t REG_SZ /d "powershell.exe -WindowStyle \""Normal\"" -ExecutionPolicy \""Unrestricted\"" -NoProfile -File \""C:\Windows\Setup\Scripts\UserOnce.ps1\""" /f;
};
);
&amp; {
[float]$complete = 0;
[float]$increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Id 0 -Activity 'Running scripts to modify the default user&#x2019;&#x2019;s registry hive. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 | Out-String -Width 1KB -Stream &gt;&gt; "C:\Windows\Setup\Scripts\DefaultUser.log";
</File>
<File path="C:\Windows\Setup\Scripts\FirstLogon.ps1">
$scripts = @(
{
cmd.exe /c "rmdir C:\Windows.old";
};
{
Remove-Item -LiteralPath @(
'C:\Windows\Panther\unattend.xml';
'C:\Windows\Panther\unattend-original.xml';
'C:\Windows\Setup\Scripts\Wifi.xml';
) -Force -ErrorAction 'SilentlyContinue' -Verbose;
};
{
reg.exe delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v NoAutoUpdate /f;
reg.exe delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /v DisableWindowsUpdateAccess /f;
};
{
$recallFeature = Get-WindowsOptionalFeature -Online -ErrorAction SilentlyContinue | Where-Object { $_.State -eq 'Enabled' -and $_.FeatureName -like 'Recall' };
if( $recallFeature ) {
Disable-WindowsOptionalFeature -Online -FeatureName 'Recall' -Remove -ErrorAction SilentlyContinue;
}
};
{
try {
$viveDir = Join-Path $env:TEMP 'ViVeTool';
$viveZip = Join-Path $env:TEMP 'ViVeTool.zip';
Invoke-WebRequest 'https://github.com/thebookisclosed/ViVe/releases/download/v0.3.4/ViVeTool-v0.3.4-IntelAmd.zip' -OutFile $viveZip;
Expand-Archive -Path $viveZip -DestinationPath $viveDir -Force;
Remove-Item -Path $viveZip -Force;
Start-Process -FilePath (Join-Path $viveDir 'ViVeTool.exe') -ArgumentList '/disable /id:47205210' -Wait -NoNewWindow;
Remove-Item -Path $viveDir -Recurse -Force;
} catch {}
};
{
if( (Get-BitLockerVolume -MountPoint $Env:SystemDrive).ProtectionStatus -eq 'On' ) {
Disable-BitLocker -MountPoint $Env:SystemDrive;
}
};
{
if( (bcdedit | Select-String 'path').Count -eq 2 ) {
bcdedit /set `{bootmgr`} timeout 0;
}
};
);
&amp; {
[float]$complete = 0;
[float]$increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Id 0 -Activity 'Running scripts to finalize your Windows installation. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 | Out-String -Width 1KB -Stream &gt;&gt; "C:\Windows\Setup\Scripts\FirstLogon.log";
</File>
</Extensions>
</unattend>

View File

@@ -970,11 +970,11 @@
</TextBlock>
</ToggleButton.Content>
</ToggleButton>
<ToggleButton Margin="0,0,5,0" Height="{DynamicResource TabButtonHeight}" Width="{DynamicResource TabButtonWidth}"
<ToggleButton Margin="0,0,5,0" Height="{DynamicResource TabButtonHeight}" Width="Auto" MinWidth="{DynamicResource TabButtonWidth}"
Background="{DynamicResource ButtonWin11ISOBackgroundColor}" Foreground="{DynamicResource ButtonWin11ISOForegroundColor}" FontWeight="Bold" Name="WPFTab5BT">
<ToggleButton.Content>
<TextBlock FontSize="{DynamicResource TabButtonFontSize}" Background="Transparent" Foreground="{DynamicResource ButtonWin11ISOForegroundColor}">
<Underline>W</Underline>in11ISO
<Underline>W</Underline>in11 Creator
</TextBlock>
</ToggleButton.Content>
</ToggleButton>
@@ -1353,7 +1353,7 @@
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- STEP 1 : Select Windows 11 ISO -->
<!-- ═══════════════════════════════════════════════════════════ -->
<Border Grid.Row="0" Style="{StaticResource BorderStyle}">
<Border Grid.Row="0" Name="WPFWin11ISOSelectSection" Style="{StaticResource BorderStyle}">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -1364,13 +1364,17 @@
<StackPanel Grid.Column="0" Margin="5,5,15,5">
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}" Margin="0,0,0,8">
Step 1 Select Windows 11 ISO
Step 1 - Select Windows 11 ISO
</TextBlock>
<TextBlock FontSize="{DynamicResource FontSize}" Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap" Margin="0,0,0,12">
TextWrapping="Wrap" Margin="0,0,0,6">
Browse to your locally saved Windows 11 ISO file. Only official ISOs
downloaded from Microsoft are supported.
</TextBlock>
<TextBlock FontSize="{DynamicResource FontSize}" Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap" Margin="0,0,0,12" FontStyle="Italic">
<Run FontWeight="Bold">NOTE:</Run> This is only meant for Fresh and New Windows installs.
</TextBlock>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -1387,7 +1391,7 @@
Background="{DynamicResource MainBackgroundColor}"/>
<Button Grid.Column="1"
Name="WPFWin11ISOBrowseButton"
Content="Browse"
Content="Browse"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"/>
</Grid>
@@ -1408,7 +1412,7 @@
<StackPanel>
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="OrangeRed" Margin="0,0,0,10">
You must use an official Microsoft ISO
!!WARNING!! You must use an official Microsoft ISO
</TextBlock>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
@@ -1425,9 +1429,9 @@
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap" Margin="12,0,0,12">
Edition : Windows 11
<LineBreak/> Language : your preferred language
<LineBreak/> Architecture : 64-bit (x64)
- Edition : Windows 11
<LineBreak/>- Language : your preferred language
<LineBreak/>- Architecture : 64-bit (x64)
</TextBlock>
<Button Name="WPFWin11ISODownloadLink"
Content="Open Microsoft Download Page"
@@ -1455,7 +1459,7 @@
<StackPanel Grid.Column="0" Margin="0,0,20,0" VerticalAlignment="Top">
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}" Margin="0,0,0,8">
Step 2 Mount &amp; Verify ISO
Step 2 - Mount &amp; Verify ISO
</TextBlock>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
@@ -1490,12 +1494,15 @@
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}"
Margin="0,6,0,4">
Available Editions:
Select Edition:
</TextBlock>
<TextBlock Name="WPFWin11ISOEditionList"
FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap"/>
<ComboBox Name="WPFWin11ISOEditionComboBox"
FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
Background="{DynamicResource MainBackgroundColor}"
BorderBrush="{DynamicResource BorderColor}"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"/>
</StackPanel>
</Border>
</Grid>
@@ -1511,7 +1518,7 @@
<StackPanel Margin="5">
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}" Margin="0,0,0,8">
Step 3 Modify install.wim
Step 3 - Modify install.wim
</TextBlock>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
@@ -1522,7 +1529,7 @@
depending on your hardware.
</TextBlock>
<Button Name="WPFWin11ISOModifyButton"
Content="Run install.wim Modification"
Content="Run Windows ISO Modification and Creator"
HorizontalAlignment="Left"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"/>
@@ -1534,77 +1541,92 @@
<!-- ═══════════════════════════════════════════════════════════ -->
<Border Grid.Row="3"
Name="WPFWin11ISOOutputSection"
Style="{StaticResource BorderStyle}"
Visibility="Collapsed">
Style="{StaticResource BorderStyle}">
<StackPanel Margin="5">
<TextBlock FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}" Margin="0,0,0,12">
Step 4 — Output: What would you like to do with the modified ISO?
</TextBlock>
<Grid>
<!-- Header row: title + Clean & Reset button -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" FontSize="{DynamicResource FontSize}" FontWeight="Bold"
Foreground="{DynamicResource MainForegroundColor}"
VerticalAlignment="Center">
Step 4 - Output: What would you like to do with the modified image?
</TextBlock>
<Button Grid.Column="1"
Name="WPFWin11ISOCleanResetButton"
Content="Clean &amp; Reset"
Foreground="OrangeRed"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"
ToolTip="Delete the temporary working directory and reset the interface back to Step 1"
Margin="12,0,0,0"/>
</Grid>
<!-- ── Choice prompt buttons ── -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Option 1: Export to ISO -->
<Border Grid.Column="0" Style="{StaticResource BorderStyle}">
<StackPanel>
<Button Name="WPFWin11ISOExportButton"
Content="1 — Export to ISO"
HorizontalAlignment="Stretch"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"
Margin="0,0,0,10"/>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap">
Save the modified content as a new bootable ISO file.
You can store it, use it in a virtual machine, or later
burn it to USB with any tool of your choice.
</TextBlock>
</StackPanel>
</Border>
<!-- Option 2: Erase & Write to USB -->
<Border Grid.Column="1" Style="{StaticResource BorderStyle}">
<StackPanel>
<!-- USB drive selector row -->
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0"
Name="WPFWin11ISOUSBDriveComboBox"
Foreground="{DynamicResource MainForegroundColor}"
Background="{DynamicResource MainBackgroundColor}"
VerticalAlignment="Center"
Margin="0,0,6,0"/>
<Button Grid.Column="1"
Name="WPFWin11ISORefreshUSBButton"
Content="↻ Refresh"
Width="Auto" Padding="8,0"
Height="{DynamicResource ButtonHeight}"/>
</Grid>
<Button Name="WPFWin11ISOWriteUSBButton"
Content="2 — Erase &amp; Write to USB"
Foreground="OrangeRed"
HorizontalAlignment="Stretch"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"
Margin="0,0,0,10"/>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap">
<Run FontWeight="Bold" Foreground="OrangeRed">!! All data on the selected USB drive will be erased !!</Run>
<LineBreak/>
Select a removable USB drive above, then click the button
to write the modified Windows 11 installation directly to it.
</TextBlock>
</StackPanel>
</Border>
<Button Grid.Column="0"
Name="WPFWin11ISOChooseISOButton"
Content="Save as an ISO File"
HorizontalAlignment="Stretch"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"/>
<Button Grid.Column="2"
Name="WPFWin11ISOChooseUSBButton"
Content="Write Directly to a USB Drive (erases drive)"
Foreground="OrangeRed"
HorizontalAlignment="Stretch"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"/>
</Grid>
<!-- ── USB write sub-panel (revealed on USB choice) ── -->
<Border Name="WPFWin11ISOOptionUSB"
Style="{StaticResource BorderStyle}"
Visibility="Collapsed"
Margin="0,8,0,0">
<StackPanel>
<TextBlock FontSize="{DynamicResource FontSize}"
Foreground="{DynamicResource MainForegroundColor}"
TextWrapping="Wrap" Margin="0,0,0,8">
<Run FontWeight="Bold" Foreground="OrangeRed">!! All data on the selected USB drive will be permanently erased !!</Run>
<LineBreak/>
Select a removable USB drive below, then click Erase &amp; Write.
</TextBlock>
<!-- USB drive selector row -->
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0"
Name="WPFWin11ISOUSBDriveComboBox"
Foreground="{DynamicResource MainForegroundColor}"
Background="{DynamicResource MainBackgroundColor}"
VerticalAlignment="Center"
Margin="0,0,6,0"/>
<Button Grid.Column="1"
Name="WPFWin11ISORefreshUSBButton"
Content="↻ Refresh"
Width="Auto" Padding="8,0"
Height="{DynamicResource ButtonHeight}"/>
</Grid>
<Button Name="WPFWin11ISOWriteUSBButton"
Content="Erase &amp; Write to USB"
Foreground="OrangeRed"
HorizontalAlignment="Stretch"
Width="Auto" Padding="12,0"
Height="{DynamicResource ButtonHeight}"
Margin="0,0,0,10"/>
</StackPanel>
</Border>
</StackPanel>
</Border>