# Enable debugging #Set-PSDebug -Trace 1 param ( [ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')] [string]$ScratchDisk, [string]$windowsisopath, [string]$imageindex, [switch]$UseSetupTemplate ) if (-not $ScratchDisk) { $ScratchDisk = Join-Path $PSScriptRoot 'working' # Set to './working' in the script's directory } else { if ($ScratchDisk -match '^[a-zA-Z]:?$') { $ScratchDisk = $ScratchDisk[0] + ':' } } Write-Output "Scratch disk set to $ScratchDisk" # Normalize windowsisopath: accept D, D:, D:\ all as drive letter D: if ($windowsisopath -match '^[a-zA-Z]:?\\?$') { $windowsisopath = $windowsisopath[0] + ':' } # Check if PowerShell execution is Restricted or AllSigned or Undefined $needchange = @("AllSigned", "Restricted", "Undefined") $curpolicy = Get-ExecutionPolicy if ($curpolicy -in $needchange) { Write-Host "Your current PowerShell Execution Policy is set to $curpolicy, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)" $response = Read-Host if ($response -eq 'yes') { Set-ExecutionPolicy RemoteSigned -Scope Process -Confirm:$false } else { Write-Host "The script cannot be run without changing the execution policy. Exiting..." exit } } # Check and run the script as admin if required $adminSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") $adminGroup = $adminSID.Translate([System.Security.Principal.NTAccount]) $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent() $myWindowsPrincipal = new-object System.Security.Principal.WindowsPrincipal($myWindowsID) $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator if (! $myWindowsPrincipal.IsInRole($adminRole)) { Write-Host "Restarting Tiny11 image creator as admin in a new window, you can close this one." $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell"; $argString = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" # Add additional parameters if they are set if ($windowsisopath) { $argString += " -windowsisopath `"$windowsisopath`"" } if ($imageindex) { $argString += " -imageindex `"$imageindex`"" } if ($UseSetupTemplate) { $argString += " -UseSetupTemplate" } $newProcess.Arguments = $argString; $newProcess.Verb = "runas"; [System.Diagnostics.Process]::Start($newProcess); exit } # Start the transcript and prepare the window Start-Transcript -Path "$ScratchDisk\tiny11.log" $Host.UI.RawUI.WindowTitle = "Tiny11 image creator" Clear-Host $hostArchitecture = $Env:PROCESSOR_ARCHITECTURE $setupMediaTemplatePath = "$PSScriptRoot\setup-media-template" New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny11\sources" | Out-Null # -- Direct file input: auto-mount ISO or extract WIM/ESD -- $mountedISO = $null # path of ISO we mounted (for cleanup) $sourceFromFile = $false # true when scratch dir populated directly from WIM/ESD if ($windowsisopath -and $windowsisopath -notmatch '^[c-zC-Z]:$') { $ext = [System.IO.Path]::GetExtension($windowsisopath).ToLower() if ($ext -eq '.iso') { Write-Host "ISO file provided - mounting: $windowsisopath" $resolvedIso = (Resolve-Path $windowsisopath).Path $mountResult = Mount-DiskImage -ImagePath $resolvedIso -PassThru -ErrorAction Stop $mountedISO = $resolvedIso $windowsisopath = ($mountResult | Get-Volume).DriveLetter + ":" Write-Host "ISO mounted at $windowsisopath" } elseif ($ext -in @('.wim', '.esd')) { $sourceFile = (Resolve-Path $windowsisopath).Path Write-Host "Direct WIM/ESD source: $sourceFile" $allIndexes = Get-WindowsImage -ImagePath $sourceFile Write-Host "Indexes in source file:" $allIndexes | ForEach-Object { Write-Host " [$($_.ImageIndex)] $($_.ImageName)" } if ($allIndexes.Count -ge 4) { # WOR-format ESD: idx 1 = setup structure, 2 = WinPE, 3 = Setup, 4+ = OS editions Write-Host "Full ESD with setup structure detected." if (-not $UseSetupTemplate) { Write-Host "Extracting setup media structure (index 1)..." Expand-WindowsImage -ImagePath $sourceFile -Index 1 -ApplyPath "$ScratchDisk\tiny11\" -ErrorAction Stop $bootWimDest = "$ScratchDisk\tiny11\sources\boot.wim" if (Test-Path $bootWimDest) { Remove-Item $bootWimDest -Force } Write-Host "Building boot.wim (PE index 2 + Setup index 3)..." & dism /English /Export-Image "/SourceImageFile:$sourceFile" "/SourceIndex:2" ` "/DestinationImageFile:$bootWimDest" /Compress:max /CheckIntegrity | Out-Null & dism /English /Export-Image "/SourceImageFile:$sourceFile" "/SourceIndex:3" ` "/DestinationImageFile:$bootWimDest" /Compress:max /CheckIntegrity | Out-Null } if ($imageindex) { $installSrcIndex = [int]$imageindex } else { $installSrcIndex = ($allIndexes | Where-Object { $_.ImageName -match 'Windows 1[01] Pro$' } | Select-Object -First 1).ImageIndex if (-not $installSrcIndex) { $installSrcIndex = $allIndexes[-1].ImageIndex } $editionName = ($allIndexes | Where-Object { $_.ImageIndex -eq $installSrcIndex }).ImageName Write-Host "Using install image index $installSrcIndex ($editionName)" } Write-Host "Extracting install image to sources\install.wim..." Export-WindowsImage -SourceImagePath $sourceFile -SourceIndex $installSrcIndex ` -DestinationImagePath "$ScratchDisk\tiny11\sources\install.wim" -CompressionType None -ErrorAction Stop $index = 1 $indexAlreadySelected = $true $sourceFromFile = $true Write-Host "Source extraction complete." } else { # Install-only WIM/ESD - no boot structure Write-Host "Install-only source (no setup structure). Copying to scratch..." if ($ext -eq '.esd') { Copy-Item $sourceFile "$ScratchDisk\tiny11\sources\install.esd" -Force Set-ItemProperty "$ScratchDisk\tiny11\sources\install.esd" -Name IsReadOnly -Value $false -ErrorAction SilentlyContinue } else { Copy-Item $sourceFile "$ScratchDisk\tiny11\sources\install.wim" -Force & takeown "/F" "$ScratchDisk\tiny11\sources\install.wim" | Out-Null & icacls "$ScratchDisk\tiny11\sources\install.wim" "/grant" "$($adminGroup.Value):(F)" | Out-Null try { Set-ItemProperty "$ScratchDisk\tiny11\sources\install.wim" -Name IsReadOnly -Value $false -ErrorAction Stop } catch {} } $sourceFromFile = $true Write-Warning "No boot structure found. ISO creation will fail without etfsboot.com and efisys.bin." Write-Warning "Use a full WOR-format ESD for a complete bootable image." } } } # -- Drive letter input (existing path) -- if (-not $sourceFromFile) { if ($windowsisopath -match '^[c-zC-Z]:$') { write-host "windows iso path: $windowsisopath" $DriveLetter = $windowsisopath } else { do { $DriveLetter = Read-Host "Please enter the drive letter for the Windows 11 image, e.g. D:" if ($DriveLetter -match '^[c-zC-Z]$') { $DriveLetter = "$DriveLetter`:" # Ensure proper format Write-Output "Drive letter set to $DriveLetter" } else { Write-Output "Invalid drive letter. Please enter a letter between C and Z." } } while ($DriveLetter -notmatch '^[c-zC-Z]:$') # Continue until valid } if ((-not $UseSetupTemplate -and (Test-Path "$DriveLetter\sources\boot.wim") -eq $false) -or (Test-Path "$DriveLetter\sources\install.wim") -eq $false) { if ((Test-Path "$DriveLetter\sources\install.esd") -eq $true) { Write-Host "Found install.esd, converting to install.wim..." # Use provided imageindex parameter or ask user if ($imageindex) { $esdIndex = $imageindex Write-Host "Using provided image index: $esdIndex" } else { Get-WindowsImage -ImagePath $DriveLetter\sources\install.esd $esdIndex = Read-Host "Please enter the image index" } Write-Host ' ' Write-Host 'Converting install.esd to install.wim. This may take a while...' Export-WindowsImage -SourceImagePath $DriveLetter\sources\install.esd -SourceIndex $esdIndex -DestinationImagePath $ScratchDisk\tiny11\sources\install.wim -Compressiontype Maximum -CheckIntegrity # After ESD conversion, the selected image becomes index 1 in the new WIM $index = 1 $indexAlreadySelected = $true Write-Host "ESD image index $esdIndex has been converted and is now index 1 in the WIM file." } else { Write-Host "Can't find Windows OS Installation files in the specified Drive Letter.." Write-Host "Please enter the correct DVD Drive Letter.." exit } } if ($UseSetupTemplate) { if (-not $indexAlreadySelected) { Write-Host "Template mode: copying install.wim from source..." Copy-Item -Path "$DriveLetter\sources\install.wim" -Destination "$ScratchDisk\tiny11\sources\install.wim" -Force | Out-Null } } else { Write-Host "Copying Windows image..." Copy-Item -Path "$DriveLetter\*" -Destination "$ScratchDisk\tiny11" -Recurse -Force | Out-Null Set-ItemProperty -Path "$ScratchDisk\tiny11\sources\install.esd" -Name IsReadOnly -Value $false > $null 2>&1 Remove-Item "$ScratchDisk\tiny11\sources\install.esd" > $null 2>&1 Write-Host "Copy complete!" Start-Sleep -Seconds 2 Clear-Host } } # -- Template mode: copy setup media base -- if ($UseSetupTemplate) { if (-not (Test-Path "$setupMediaTemplatePath")) { Write-Error "setup-media-template folder not found: $setupMediaTemplatePath" exit 1 } Write-Host "Copying setup media template to scratch..." Copy-Item -Path "$setupMediaTemplatePath\*" -Destination "$ScratchDisk\tiny11" -Recurse -Force | Out-Null Write-Host "Template copy complete." } # Only ask for image index if we haven't already selected one during ESD conversion if ($indexAlreadySelected) { Write-Host "Using converted image at index: $index" } elseif ($imageindex) { $index = $imageindex Write-Host "Using provided image index: $index" } else { Write-Host "Getting image information..." Get-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim $index = Read-Host "Please enter the image index : " $ImagesIndex = (Get-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim).ImageIndex while ($ImagesIndex -notcontains $index) { $index = Read-Host "Please enter a valide image index : " } } Write-Host "Mounting Windows image. This may take a while." $wimFilePath = "$ScratchDisk\tiny11\sources\install.wim" & takeown "/F" $wimFilePath & icacls $wimFilePath "/grant" "$($adminGroup.Value):(F)" try { Set-ItemProperty -Path $wimFilePath -Name IsReadOnly -Value $false -ErrorAction Stop } catch { # This block will catch the error and suppress it. } New-Item -ItemType Directory -Force -Path "$ScratchDisk\scratchdir" > $null Mount-WindowsImage -ImagePath $wimFilePath -Index $index -Path $ScratchDisk\scratchdir # Powershell dism module does not have direct equivalent for /Get-Intl $imageIntl = & dism /English /Get-Intl "/Image:$($ScratchDisk)\scratchdir" $languageLine = $imageIntl -split '\n' | Where-Object { $_ -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' } if ($languageLine) { $languageCode = $Matches[1] Write-Host "Default system UI language code: $languageCode" } else { Write-Host "Default system UI language code not found." } # Defined in (Microsoft.Dism.Commands.ImageInfoObject).Architecture formatting script # 0 -> x86, 5 -> arm(currently unused), 6 -> ia64(currently unused), 9 -> x64, 12 -> arm64 switch ((Get-WindowsImage -ImagePath $wimFilePath -Index $index).Architecture) { 0 { $architecture = "x86" } 9 { $architecture = "amd64" } 12 { $architecture = "arm64" } } if ($architecture) { Write-Host "Architecture: $architecture" } else { Write-Host "Architecture information not found." } Write-Host "Mounting complete! Performing removal of applications..." $packages = Get-ProvisionedAppxPackage -Path "$ScratchDisk\scratchdir" | ForEach-Object { $_.PackageName } $packagePrefixes = @( 'Clipchamp.Clipchamp_', 'Microsoft.BingNews_', 'Microsoft.BingSearch_', 'Microsoft.BingWeather_', 'Microsoft.MicrosoftEdge.Stable_', 'Microsoft.GamingApp_', 'Microsoft.Getstarted_', 'Microsoft.MicrosoftOfficeHub_', 'Microsoft.MicrosoftSolitaireCollection_', 'Microsoft.OutlookForWindows_', 'Microsoft.People_', 'Microsoft.PowerAutomateDesktop_', 'Microsoft.Todos_', 'Microsoft.Windows.DevHome_', 'Microsoft.WindowsAlarms_', 'microsoft.windowscommunicationsapps_', 'Microsoft.WindowsFeedbackHub_', 'Microsoft.WindowsMaps_', 'Microsoft.WindowsSoundRecorder_', 'Microsoft.ZuneMusic_', 'Microsoft.ZuneVideo_', 'Microsoft.Xbox.TCUI_', 'Microsoft.XboxGamingOverlay_', 'Microsoft.XboxGameOverlay_', 'Microsoft.XboxSpeechToTextOverlay_', 'MicrosoftCorporationII.MicrosoftFamily_', 'MicrosoftTeams_', 'MSTeams_', 'Microsoft.549981C3F5F10_', 'Microsoft.Copilot_', 'Microsoft.MSPaint_', 'Microsoft.Paint_', 'Microsoft.YourPhone_', 'Microsoft.WindowsCalculator_', 'Microsoft.WindowsCamera_', 'Microsoft.MicrosoftStickyNotes_', 'Microsoft.ScreenSketch_', 'MicrosoftWindows.Client.WebExperience_', 'MicrosoftWindows.CrossDevice_' ) $packagesToRemove = foreach ($pkg in $packages) { if ($packagePrefixes | Where-Object { $pkg -like "$_*" }) { $pkg } } foreach ($package in $packagesToRemove) { Write-Host "Removing $package..." Remove-AppxProvisionedPackage -Path "$ScratchDisk\scratchdir" -PackageName "$package" | Out-Null } Write-Host "Removing Edge..." # Remove Edge directories Write-Host "Removing Edge directories..." if (Test-Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\Edge") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\Edge" '/r' '/d' 'y' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\Edge" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\Edge" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } if (Test-Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeUpdate") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeUpdate" '/r' '/d' 'y' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeUpdate" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeUpdate" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } if (Test-Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeCore") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeCore" '/r' '/d' 'y' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeCore" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeCore" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } # Also check for Edge in Program Files (some installations) if (Test-Path "$ScratchDisk\scratchdir\Program Files\Microsoft\Edge") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Program Files\Microsoft\Edge" '/r' '/d' 'y' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Program Files\Microsoft\Edge" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files\Microsoft\Edge" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } if (Test-Path "$ScratchDisk\scratchdir\Program Files\Microsoft\EdgeUpdate") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Program Files\Microsoft\EdgeUpdate" '/r' '/d' 'y' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Program Files\Microsoft\EdgeUpdate" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files\Microsoft\EdgeUpdate" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } # Remove architecture-specific Edge WebView components if ($architecture -eq 'amd64') { $folderPath = Get-ChildItem -Path "$ScratchDisk\scratchdir\Windows\WinSxS" -Filter "amd64_microsoft-edge-webview_31bf3856ad364e35*" -Directory -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName if ($folderPath) { foreach ($folder in $folderPath) { if (Test-Path $folder) { & 'takeown' '/f' $folder '/r' '/d' 'y' | Out-Null & 'icacls' $folder '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } } } else { Write-Host "AMD64 Edge WebView folder not found." } } elseif ($architecture -eq 'arm64') { $folderPath = Get-ChildItem -Path "$ScratchDisk\scratchdir\Windows\WinSxS" -Filter "arm64_microsoft-edge-webview_31bf3856ad364e35*" -Directory -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName if ($folderPath) { foreach ($folder in $folderPath) { if (Test-Path $folder) { & 'takeown' '/f' $folder '/r' '/d' 'y' | Out-Null & 'icacls' $folder '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } } } else { Write-Host "ARM64 Edge WebView folder not found." } } else { Write-Host "Unknown architecture: $architecture" } # Remove Microsoft Edge WebView directory #if (Test-Path "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview") { # & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" '/r' '/d' 'y' | Out-Null # & 'icacls' "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null # Remove-Item -Path "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null #} Write-Host "Removing OneDrive..." # Remove OneDrive setup file if (Test-Path "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" -Force -ErrorAction SilentlyContinue | Out-Null } if (Test-Path "$ScratchDisk\scratchdir\Windows\SysWOW64\OneDriveSetup.exe") { & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\SysWOW64\OneDriveSetup.exe" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\SysWOW64\OneDriveSetup.exe" '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Windows\SysWOW64\OneDriveSetup.exe" -Force -ErrorAction SilentlyContinue | Out-Null } Write-Host "Removal complete!" Start-Sleep -Seconds 2 $replaceBranding = $true # Set to $false to skip branding replacement if ($replaceBranding) { # Replace system files for OEM branding Write-Host "Replacing system files for OEM branding..." # Take ownership and grant permissions before copying & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\basebrd.dll" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\basebrd.dll" '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\en-US\basebrd.dll.mui" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\en-US\basebrd.dll.mui" '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\Branding\shellbrd\shellbrd.dll" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\Branding\shellbrd\shellbrd.dll" '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null # Now copy the new files Copy-Item -Path "$PSScriptRoot\includes\branding-resources\system\basebrd.dll" -Destination "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\basebrd.dll" -Force | Out-Null Copy-Item -Path "$PSScriptRoot\includes\branding-resources\system\basebrd.dll.mui" -Destination "$ScratchDisk\scratchdir\Windows\Branding\Basebrd\en-US\basebrd.dll.mui" -Force | Out-Null Copy-Item -Path "$PSScriptRoot\includes\branding-resources\system\shellbrd.dll" -Destination "$ScratchDisk\scratchdir\Windows\Branding\shellbrd\shellbrd.dll" -Force | Out-Null $brandingBootRes = "$PSScriptRoot\includes\branding-resources\system\bootres.dll" if (Test-Path $brandingBootRes) { Write-Host "Copying bootres.dll..." foreach ($bootresPath in @( "$ScratchDisk\scratchdir\Windows\Boot\EFI\bootres.dll", "$ScratchDisk\scratchdir\Windows\Boot\PCAT\bootres.dll" )) { if (Test-Path $bootresPath) { & 'takeown' '/f' $bootresPath | Out-Null & 'icacls' $bootresPath '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null Copy-Item -Path $brandingBootRes -Destination $bootresPath -Force | Out-Null } } } } Start-Sleep -Seconds 2 Clear-Host Write-Host "Loading registry..." reg load HKLM\zCOMPONENTS $ScratchDisk\scratchdir\Windows\System32\config\COMPONENTS | Out-Null reg load HKLM\zDEFAULT $ScratchDisk\scratchdir\Windows\System32\config\default | Out-Null reg load HKLM\zNTUSER $ScratchDisk\scratchdir\Users\Default\ntuser.dat | Out-Null reg load HKLM\zSOFTWARE $ScratchDisk\scratchdir\Windows\System32\config\SOFTWARE | Out-Null reg load HKLM\zSYSTEM $ScratchDisk\scratchdir\Windows\System32\config\SYSTEM | Out-Null Write-Host "Bypassing system requirements(on the system image):" & 'reg' 'add' 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassCPUCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassRAMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassSecureBootCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassStorageCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassTPMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\MoSetup' '/v' 'AllowUpgradesWithUnsupportedTPMOrCPU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' '/v' 'BypassNRO' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Disabling Sponsored Apps:" & 'reg' 'add' 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'OemPreInstalledAppsEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'PreInstalledAppsEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SilentInstalledAppsEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'ContentDeliveryAllowed' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'FeatureManagementEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'PreInstalledAppsEverEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SoftLandingEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContentEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-310093Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-338388Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-338389Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-338393Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-353694Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-353696Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SystemPaneSuggestionsEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'delete' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\Subscriptions' '/f' | Out-Null & 'reg' 'delete' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SuggestedApps' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\PushToInstall' '/v' 'DisablePushToInstall' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\MRT' '/v' 'DontOfferThroughWUAU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' '/v' 'DisableConsumerAccountStateContent' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' '/v' 'DisableCloudOptimizedContent' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' '/v' 'DisableWindowsConsumerFeatures' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\Start' '/v' 'ConfigureStartPins' '/t' 'REG_SZ' '/d' '{"pinnedList": [{}]}' '/f' | Out-Null Write-Host "Configuring Windows Update to prevent cloud feature injection..." # Disable feature updates (but allow security) & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' '/v' 'DeferFeatureUpdates' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' '/v' 'DeferFeatureUpdatesPeriodInDays' '/t' 'REG_DWORD' '/d' '365' '/f' | Out-Null # Disable driver updates from Windows Update (cloud source) & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' '/v' 'ExcludeWUDriversInQualityUpdate' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Disabling Delivery Optimization (P2P cloud updates)..." & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization' '/v' 'DODownloadMode' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\ControlSet001\Services\DoSvc' '/v' 'Start' '/t' 'REG_DWORD' '/d' '4' '/f' | Out-Null Write-Host "Disabling Diagnostic Data Viewer..." & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Diagnostics\DiagTrack' '/v' 'ShowedToastAtLevel' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\ControlSet001\Services\DiagTrack' '/v' 'Start' '/t' 'REG_DWORD' '/d' '4' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' '/v' 'Start' '/t' 'REG_DWORD' '/d' '4' '/f' | Out-Null Write-Host "Disabling Cloud Store sync..." # Windows.CloudStore.dll data sync & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\SettingSync' '/v' 'DisableSettingSync' '/t' 'REG_DWORD' '/d' '2' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\SettingSync' '/v' 'DisableSettingSyncUserOverride' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null # Per-user cloud sync disable & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\SettingSync' '/v' 'SyncPolicy' '/t' 'REG_DWORD' '/d' '5' '/f' | Out-Null Write-Host "Disabling Windows Insider Program..." # Prevents cloud-based preview builds & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\PreviewBuilds' '/v' 'AllowBuildPreview' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\PreviewBuilds' '/v' 'EnableConfigFlighting' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Disabling Windows Feedback..." & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' '/v' 'DoNotShowFeedbackNotifications' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Siuf\Rules' '/v' 'NumberOfSIUFInPeriod' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Siuf\Rules' '/v' 'PeriodInNanoSeconds' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Disabling Experimentation and Configuration Service..." # Prevents A/B testing and cloud-based feature rollouts & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\System' '/v' 'AllowExperimentation' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\PolicyManager\default\System\AllowExperimentation' '/v' 'value' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Disabling Start Menu Iris recommendations" & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' '/v' 'Start_IrisRecommendations' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Enabling Local Accounts on OOBE:" & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' '/v' 'BypassNRO' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Copy-Item -Path "$PSScriptRoot\includes\autounattend-win11.xml" -Destination "$ScratchDisk\scratchdir\Windows\System32\Sysprep\autounattend.xml" -Force | Out-Null Write-Host "Disabling Reserved Storage:" & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager' '/v' 'ShippedWithReserves' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Disabling BitLocker Device Encryption" & 'reg' 'add' 'HKLM\zSYSTEM\ControlSet001\Control\BitLocker' '/v' 'PreventDeviceEncryption' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Disabling Chat icon:" & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat' '/v' 'ChatIcon' '/t' 'REG_DWORD' '/d' '3' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' '/v' 'TaskbarMn' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null Write-Host "Removing Edge related registries" & 'reg' 'delete' 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge' '/f' | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update' '/f' | Out-Null Write-Host "Disabling OneDrive folder backup" & 'reg' 'add' "HKLM\zSOFTWARE\Policies\Microsoft\Windows\OneDrive" '/v' 'DisableFileSyncNGSC' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Disabling Telemetry:" & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo' '/v' 'Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Privacy' '/v' 'TailoredExperiencesWithDiagnosticDataEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Speech_OneCore\Settings\OnlineSpeechPrivacy' '/v' 'HasAccepted' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Input\TIPC' '/v' 'Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' '/v' 'RestrictImplicitInkCollection' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization' '/v' 'RestrictImplicitTextCollection' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\InputPersonalization\TrainedDataStore' '/v' 'HarvestContacts' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Personalization\Settings' '/v' 'AcceptedPrivacyPolicy' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' '/v' 'AllowTelemetry' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' '/v' 'Start' '/t' 'REG_DWORD' '/d' '4' '/f' | Out-Null ## Disable Windows Spotlight and tips on lockscreen & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'RotatingLockScreenEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'RotatingLockScreenOverlayEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'SubscribedContent-338387Enabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null ## Prevents installation of DevHome and Outlook Write-Host "Prevents installation of DevHome and Outlook:" & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate' '/v' 'workCompleted' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\DevHomeUpdate' '/v' 'workCompleted' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' '/f' | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate' '/f' | Out-Null ## Set default wallpaper and dark mode Write-Host "Setting default dark mode..." & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'SystemUsesLightTheme' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'AppsUseLightTheme' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'EnableTransparency' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'SystemUsesLightTheme' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'AppsUseLightTheme' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' '/v' 'EnableTransparency' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Setting up the default wallpaper..." & 'reg' 'add' 'HKLM\zDEFAULT\Control Panel\Desktop' '/v' 'WallPaper' '/t' 'REG_SZ' '/d' '%SystemRoot%\Windows\Web\Wallpaper\Windows\flooded-city.jpg' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers' '/v' 'WallpaperStyle' '/t' 'REG_DWORD' '/d' '10' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Control Panel\Desktop' '/v' 'WallPaper' '/t' 'REG_SZ' '/d' '%SystemRoot%\Windows\Web\Wallpaper\Windows\flooded-city.jpg' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers' '/v' 'WallpaperStyle' '/t' 'REG_DWORD' '/d' '10' '/f' | Out-Null Write-Host "Setting up the default lockscreen..." & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Lock Screen' '/v' 'LandscapeAssetPath' '/t' 'REG_SZ' '/d' '%SystemRoot%\Windows\Web\Wallpaper\Windows\leafy-greens.jpg' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Lock Screen' '/v' 'LandscapeAssetPath' '/t' 'REG_SZ' '/d' '%SystemRoot%\Windows\Web\Wallpaper\Windows\leafy-greens.jpg' '/f' | Out-Null ## Align the taskbar to the left Write-Host "Aligning the taskbar to the left..." & 'reg' 'add' 'HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' '/v' 'TaskbarAl' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' '/v' 'TaskbarAl' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null ## Add first run key to disable OOBE on first boot #Write-Host "Adding First Run key to disable OOBE on first boot..." #& 'reg' 'add' 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' '/v' 'FirstRunCompleted' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null ## Run winsetupcomplete.ps1 on first boot #Write-Host "Setting up winsetupcomplete.ps1 to run on first boot..." #reg add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Run" /v "FirstSetup" /t REG_SZ /d "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File \"C:\Windows\Setup\Scripts\FirstLogon.ps1\"" /f #& 'reg' 'add' 'HKLM\zNTUSER\Microsoft\Windows\CurrentVersion\RunOnce' '/v' 'FirstSetup' '/t' 'REG_SZ' '/d' 'Powershell -ExecutionPolicy Bypass -File "%SystemRoot%\Windows\Setup\Scripts\winsetupcomplete.ps1"' '/f' | Out-Null ## this function allows PowerShell to take ownership of the Scheduled Tasks registry key from TrustedInstaller. Based on Jose Espitia's script. function Enable-Privilege { param( [ValidateSet( "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")] $Privilege, ## The process on which to adjust the privilege. Defaults to the current process. $ProcessId = $pid, ## Switch to disable the privilege, rather than enable it. [Switch] $Disable ) $definition = @' using System; using System.Runtime.InteropServices; public class AdjPriv { [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } internal const int SE_PRIVILEGE_ENABLED = 0x00000002; internal const int SE_PRIVILEGE_DISABLED = 0x00000000; internal const int TOKEN_QUERY = 0x00000008; internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; public static bool EnablePrivilege(long processHandle, string privilege, bool disable) { bool retVal; TokPriv1Luid tp; IntPtr hproc = new IntPtr(processHandle); IntPtr htok = IntPtr.Zero; retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; } else { tp.Attr = SE_PRIVILEGE_ENABLED; } retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); return retVal; } } '@ $processHandle = (Get-Process -id $ProcessId).Handle $type = Add-Type $definition -PassThru $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable) } Enable-Privilege SeTakeOwnershipPrivilege # Take ownership of scheduled tasks registry key Write-Host "Taking ownership of scheduled tasks registry key..." $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) $regACL = $regKey.GetAccessControl() $regACL.SetOwner($adminGroup) $regKey.SetAccessControl($regACL) $regKey.Close() Write-Host "Owner changed to Administrators." $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::ChangePermissions) $regACL = $regKey.GetAccessControl() $regRule = New-Object System.Security.AccessControl.RegistryAccessRule ($adminGroup, "FullControl", "ContainerInherit", "None", "Allow") $regACL.SetAccessRule($regRule) $regKey.SetAccessControl($regACL) Write-Host "Permissions modified for Administrators group." Write-Host "Registry key permissions successfully updated." $regKey.Close() # Take ownership of Explorer Advanced settings Write-Host "Taking ownership of Explorer Advanced settings..." $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) $regACL = $regKey.GetAccessControl() $regACL.SetOwner($adminGroup) $regKey.SetAccessControl($regACL) $regKey.Close() Write-Host "Explorer Advanced owner changed to Administrators." $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::ChangePermissions) $regACL = $regKey.GetAccessControl() $regRule = New-Object System.Security.AccessControl.RegistryAccessRule ($adminGroup, "FullControl", "ContainerInherit", "None", "Allow") $regACL.SetAccessRule($regRule) $regKey.SetAccessControl($regACL) Write-Host "Explorer Advanced permissions modified for Administrators group." Write-Host "Explorer Advanced registry key permissions successfully updated." $regKey.Close() # Clean up settings menu #Write-Host "Cleaning up Settings menu..." #& 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' '/v' 'SettingsPageVisibility' '/t' 'REG_SZ' '/d' 'hide:virus;mobile-devices;gaming;cortana;search;maps;yourinfo;workplace;backup;sync;findmydevice;developers;activation;deviceencryption' '/f' | Out-Null Write-Host "Disabling widgets in taskbar..." & 'reg' 'add' "HKLM\zDEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" '/v' "TaskbarDa" '/t' "REG_DWORD" '/d' "0" '/f' | Out-Null & 'reg' 'add' "HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" '/v' "TaskbarDa" '/t' "REG_DWORD" '/d' "0" '/f' | Out-Null # Delete scheduled tasks (with error suppression for missing keys) Write-Host 'Deleting Application Compatibility Appraiser...' & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{0600DD45-FAF2-4131-A006-0B17509B9F78}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{A0C71CB8-E8F0-498A-901D-4EDA09E07FF4}' '/f' 2>$null | Out-Null Write-Host 'Deleting Customer Experience Improvement Program...' & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{4738DE7A-BCC1-4E2D-B1B0-CADB044BFA81}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{6FAC31FA-4A85-4E64-BFD5-2154FF4594B3}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{FC931F16-B50A-472E-B061-B6F79A71EF59}' '/f' 2>$null | Out-Null Write-Host 'Deleting Program Data Updater...' & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{0671EB05-7D95-4153-A32B-1426B9FE61DB}' '/f' 2>$null | Out-Null Write-Host 'Deleting autochk proxy...' & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{87BF85F4-2CE1-4160-96EA-52F554AA28A2}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{8A9C643C-3D74-4099-B6BD-9C6D170898B1}' '/f' 2>$null | Out-Null Write-Host 'Deleting QueueReporting...' & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{E3176A65-4E44-4ED3-AA73-3283660ACB9C}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{6FD85B93-7A13-4DCA-B793-1D7D18FEAC39}' '/f' 2>$null | Out-Null Write-Host "Deleting OneDrive Standalone Update Task..." & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{A69BA1DE-BF15-4BC1-9201-71BB77CA4FB6}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{B8434E90-F460-45BE-AE61-969D68C85636}' '/f' 2>$null | Out-Null & 'reg' 'delete' 'HKLM\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{CE45C6EF-7F33-4F57-B81E-9535B89EBC2B}' '/f' 2>$null | Out-Null Write-Host "Tweaking complete!" Write-Host "Unmounting Registry..." $regKey.Close() reg unload HKLM\zCOMPONENTS | Out-Null reg unload HKLM\zDRIVERS | 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 Write-Host "Cleaning up image..." dism.exe /Image:$ScratchDisk\scratchdir /Cleanup-Image /StartComponentCleanup /ResetBase Write-Host "Cleanup complete." Write-Host ' ' Write-Host "Unmounting image..." Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save Write-Host "Exporting image..." # Compressiontype Recovery is not supported with PShell https://learn.microsoft.com/en-us/powershell/module/dism/export-windowsimage?view=windowsserver2022-ps#-compressiontype #Export-WindowsImage -SourceImagePath $ScratchDisk\tiny11\sources\install.wim -SourceIndex $index -DestinationImagePath $ScratchDisk\tiny11\sources\install2.wim -CompressionType Fast #& dism /English /Export-Image "/SourceImageFile:$ScratchDisk\tiny11\sources\install.wim" "/SourceIndex:$index" "/DestinationImageFile:$ScratchDisk\tiny11\sources\install2.wim" /Compress:max #Remove-Item -Path "$ScratchDisk\tiny11\sources\install.wim" -Force | Out-Null #Rename-Item -Path "$ScratchDisk\tiny11\sources\install2.wim" -NewName "install.wim" | Out-Null # Run `Export-WindowsImage` with undocumented CompressionType "LZMS" (which is the same compression used for Recovery from dism.exe) Export-WindowsImage -SourceImagePath "$ScratchDisk\tiny11\sources\install.wim" -SourceIndex $index -DestinationImagePath "$ScratchDisk\tiny11\sources\install2.wim" -CompressionType "LZMS" if (Test-Path "$ScratchDisk\tiny11\sources\install2.wim") { Move-Item -Path "$ScratchDisk\tiny11\sources\install2.wim" -Destination "$ScratchDisk\tiny11\sources\install.wim" -Force | Out-Null } else { Write-Warning "LZMS re-compression failed (OOM?). Continuing with original install.wim." } Write-Host "Windows image completed. Continuing with boot.wim." Start-Sleep -Seconds 2 Clear-Host Write-Host "Mounting boot image:" $wimFilePath = "$ScratchDisk\tiny11\sources\boot.wim" & takeown "/F" $wimFilePath | Out-Null & icacls $wimFilePath "/grant" "$($adminGroup.Value):(F)" Set-ItemProperty -Path $wimFilePath -Name IsReadOnly -Value $false Mount-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\boot.wim -Index 2 -Path $ScratchDisk\scratchdir Write-Host "Loading registry..." reg load HKLM\zCOMPONENTS $ScratchDisk\scratchdir\Windows\System32\config\COMPONENTS reg load HKLM\zDEFAULT $ScratchDisk\scratchdir\Windows\System32\config\default reg load HKLM\zNTUSER $ScratchDisk\scratchdir\Users\Default\ntuser.dat reg load HKLM\zSOFTWARE $ScratchDisk\scratchdir\Windows\System32\config\SOFTWARE reg load HKLM\zSYSTEM $ScratchDisk\scratchdir\Windows\System32\config\SYSTEM Write-Host "Bypassing system requirements(on the setup image)..." & 'reg' 'add' 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassCPUCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassRAMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassSecureBootCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassStorageCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassTPMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null & 'reg' 'add' 'HKLM\zSYSTEM\Setup\MoSetup' '/v' 'AllowUpgradesWithUnsupportedTPMOrCPU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null Write-Host "Tweaking complete! Unmounting Registry..." $regKey.Close() reg unload HKLM\zCOMPONENTS | Out-Null reg unload HKLM\zDRIVERS | Out-Null reg unload HKLM\zDEFAULT | Out-Null reg unload HKLM\zNTUSER | Out-Null $regKey.Close() reg unload HKLM\zSOFTWARE | Out-Null reg unload HKLM\zSYSTEM | Out-Null if ($replaceBranding -and (Test-Path $brandingBootRes)) { Write-Host "Copying bootres.dll to boot image..." foreach ($bootresPath in @( "$ScratchDisk\scratchdir\Windows\Boot\EFI\bootres.dll", "$ScratchDisk\scratchdir\Windows\Boot\PCAT\bootres.dll", "$ScratchDisk\scratchdir\Windows\Boot\Resources\bootres.dll" )) { if (Test-Path $bootresPath) { & 'takeown' '/f' $bootresPath | Out-Null & 'icacls' $bootresPath '/grant' "$($adminGroup.Value):(F)" '/C' | Out-Null Copy-Item -Path $brandingBootRes -Destination $bootresPath -Force | Out-Null } } } # Change the background.bmp in the sources folder of the boot image & takeown "/F" "$ScratchDisk\scratchdir\sources\background.bmp" | Out-Null & icacls "$ScratchDisk\scratchdir\sources\background.bmp" "/grant" "$($adminGroup.Value):(F)" Remove-Item -Path "$ScratchDisk\scratchdir\sources\background.bmp" -Force | Out-Null Copy-Item -Path "$PSScriptRoot\includes\branding-resources\setup-bg.bmp" -Destination "$ScratchDisk\scratchdir\sources\background.bmp" -Force | Out-Null # Change the setup.bmp in the system32 folder of the boot image & takeown "/F" "$ScratchDisk\scratchdir\Windows\system32\setup.bmp" | Out-Null & icacls "$ScratchDisk\scratchdir\Windows\system32\setup.bmp" "/grant" "$($adminGroup.Value):(F)" Remove-Item -Path "$ScratchDisk\scratchdir\Windows\system32\setup.bmp" -Force | Out-Null Copy-Item -Path "$PSScriptRoot\includes\branding-resources\setup-bg.bmp" -Destination "$ScratchDisk\scratchdir\Windows\system32\setup.bmp" -Force | Out-Null & takeown "/F" "$ScratchDisk\scratchdir\sources\spwizimg.dll" | Out-Null & icacls "$ScratchDisk\scratchdir\sources\spwizimg.dll" "/grant" "$($adminGroup.Value):(F)" # Copy in new spwizimg.dll with custom spwizimg.dll resource if it exists if (Test-Path -Path "$PSScriptRoot\includes\spwizimg.dll") { Write-Host "Custom spwizimg.dll found. Replacing in boot image..." Copy-Item -Path "$PSScriptRoot\includes\spwizimg.dll" -Destination "$ScratchDisk\scratchdir\sources\spwizimg.dll" -Force | Out-Null } # If there is a spwizimg-resources folder, use the resources inside to modify spwizimg.dll elseif (Test-Path -Path "$PSScriptRoot\includes\branding-resources\spwizimg-resources\" ) { Write-Host "Custom spwizimg-resources folder found. Modifying spwizimg.dll in boot image..." $resourceFiles = Get-ChildItem -Path "$PSScriptRoot\includes\branding-resources\spwizimg-resources\" -File # Create a copy of spwizimg.dll to work on Copy-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg.dll" -Destination "$ScratchDisk\scratchdir\sources\spwizimg-temp.dll" -Force | Out-Null foreach ($resourceFile in $resourceFiles) { $resourceName = $resourceFile.Name $resourcePath = $resourceFile.FullName # Extract resource ID from the filename (format: 405.png) if ($resourceName -match "^(\d+)\.png$") { # If the name is "setup-bg.png", set resource ID to 517 if ($resourceName -eq "setup-bg.png") { $resourceId = 517 } else { $resourceId = $matches[1] } # Use Resource Hacker to add/overwrite the resource in spwizimg.dll Start-Process -FilePath "$PSScriptRoot\includes\utils\ResourceHacker.exe" -ArgumentList ` "-open `"$ScratchDisk\scratchdir\sources\spwizimg-temp.dll`"", ` "-save `"$ScratchDisk\scratchdir\sources\spwizimg-temp.dll2`"", ` "-action addoverwrite", ` "-resource `"$resourcePath`"", ` "-mask PNG,$resourceId,1033" ` -NoNewWindow -Wait # Replace the temp dll with the modified one for the next iteration Remove-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg-temp.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg-temp.dll2" -NewName "spwizimg-temp.dll" | Out-Null } } # After all resources have been processed, replace the original spwizimg.dll Remove-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg-temp.dll" -NewName "spwizimg.dll" | Out-Null } # If no custom spwizimg.dll or spwizimg-resources folder, just replace the setup background image else { Write-Host "No custom spwizimg.dll or resources found. Replacing setup background image in spwizimg.dll..." Start-Process -FilePath "$PSScriptRoot\includes\utils\ResourceHacker.exe" -ArgumentList ` "-open `"$ScratchDisk\scratchdir\sources\spwizimg.dll`"", ` "-save `"$ScratchDisk\scratchdir\sources\spwizimg.dll2`"", ` "-action addoverwrite", ` "-resource `"$PSScriptRoot\includes\branding-resources\spwizimg-resources\setup-bg.png`"", ` "-mask IMAGE,517,1033" ` -NoNewWindow -Wait Remove-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\scratchdir\sources\spwizimg.dll2" -NewName "spwizimg.dll" | Out-Null } Write-Host "Unmounting image..." Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save Clear-Host Write-Host "The tiny11 image is now completed. Proceeding with the making of the ISO..." Write-Host "Copying unattended file for bypassing MS account on OOBE..." Copy-Item -Path "$PSScriptRoot\includes\autounattend-win11.xml" -Destination "$ScratchDisk\tiny11\autounattend.xml" -Force | Out-Null # If there is a $OEM$ folder, copy it to the setup image if (Test-Path -Path "${PSScriptRoot}\includes\`$OEM$") { Write-Host 'Adding $OEM$ to the setup image...' Copy-Item -Path "${PSScriptRoot}\includes\`$OEM$" -Destination "$ScratchDisk\tiny11\sources\`$OEM$" -Recurse -Force | Out-Null if (Test-Path "$PSScriptRoot\includes\utils\multi-staller\dist\MultiStaller.exe") { Copy-Item -Path "$PSScriptRoot\includes\utils\multi-staller\dist\MultiStaller.exe" -Destination "$ScratchDisk\tiny11\sources\`$OEM$\`$$\OEM\" -Force | Out-Null } } # If there is a WinPE_Drivers folder, copy it to the setup image if (Test-Path -Path "${PSScriptRoot}\includes\WinPE_Drivers") { Write-Host 'Adding WinPE_Drivers to the setup image...' Copy-Item -Path "${PSScriptRoot}\includes\WinPE_Drivers" -Destination "$ScratchDisk\tiny11\WinPE_Drivers" -Recurse -Force | Out-Null } # Change the setup background bmp in the sources folder Write-Host "Changing setup background image in setup image..." & takeown "/F" "$ScratchDisk\tiny11\sources\background_cli.bmp" | Out-Null & icacls "$ScratchDisk\tiny11\sources\background_cli.bmp" "/grant" "$($adminGroup.Value):(F)" Copy-Item -Path "$PSScriptRoot\includes\branding-resources\setup-bg.bmp" -Destination "$ScratchDisk\tiny11\sources\background_cli2.bmp" -Force | Out-Null Remove-Item -Path "$ScratchDisk\tiny11\sources\background_cli.bmp" -Force | Out-Null Rename-Item -Path "$ScratchDisk\tiny11\sources\background_cli2.bmp" -NewName "background_cli.bmp" | Out-Null # Change the setup image spwizimg.dll in the sources folder & takeown "/F" "$ScratchDisk\tiny11\sources\spwizimg.dll" | Out-Null & icacls "$ScratchDisk\tiny11\sources\spwizimg.dll" "/grant" "$($adminGroup.Value):(F)" # Copy in new spwizimg.dll with custom spwizimg.dll resource if it exists if (Test-Path -Path "$PSScriptRoot\includes\spwizimg.dll") { Write-Host "Custom spwizimg.dll found. Replacing in setup image..." Copy-Item -Path "$PSScriptRoot\includes\spwizimg.dll" -Destination "$ScratchDisk\tiny11\sources\spwizimg.dll" -Force | Out-Null } # If there is a spwizimg-resources folder, use the resources inside to modify spwizimg.dll elseif (Test-Path -Path "$PSScriptRoot\includes\spwizimg-res\") { Write-Host "Custom spwizimg-resources folder found. Modifying spwizimg.dll in setup image..." $resourceFiles = Get-ChildItem -Path "$PSScriptRoot\includes\branding-resources\spwizimg-resources\" -File # Create a copy of spwizimg.dll to work on Copy-Item -Path "$ScratchDisk\tiny11\sources\spwizimg.dll" -Destination "$ScratchDisk\tiny11\sources\spwizimg-temp.dll" -Force | Out-Null foreach ($resourceFile in $resourceFiles) { $resourceName = $resourceFile.Name $resourcePath = $resourceFile.FullName # Extract resource ID from the filename (format: 405.png) if ($resourceName -match "^(\d+)\.png$") { # If the name is "setup-bg.png", set resource ID to 517 if ($resourceName -eq "setup-bg.png") { $resourceId = 517 } else { $resourceId = $matches[1] } # Use Resource Hacker to add/overwrite the resource in spwizimg.dll Start-Process -FilePath "$PSScriptRoot\includes\utils\ResourceHacker.exe" -ArgumentList ` "-open `"$ScratchDisk\tiny11\sources\spwizimg-temp.dll`"", ` "-save `"$ScratchDisk\tiny11\sources\spwizimg-temp.dll2`"", ` "-action addoverwrite", ` "-resource `"$resourcePath`"", ` "-mask PNG,$resourceId,1033" ` -NoNewWindow -Wait # Replace the temp dll with the modified one for the next iteration Remove-Item -Path "$ScratchDisk\tiny11\sources\spwizimg-temp.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\tiny11\sources\spwizimg-temp.dll2" -NewName "spwizimg-temp.dll" | Out-Null } } # After all resources have been processed, replace the original spwizimg.dll Remove-Item -Path "$ScratchDisk\tiny11\sources\spwizimg.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\tiny11\sources\spwizimg-temp.dll" -NewName "spwizimg.dll" | Out-Null } # If no custom spwizimg.dll or spwizimg-resources folder, just replace the setup background image else { Write-Host "No custom spwizimg.dll or resources found. Replacing setup background image in spwizimg.dll..." Start-Process -FilePath "$PSScriptRoot\includes\utils\ResourceHacker.exe" -ArgumentList ` "-open `"$ScratchDisk\tiny11\sources\spwizimg.dll`"", ` "-save `"$ScratchDisk\tiny11\sources\spwizimg.dll2`"", ` "-action addoverwrite", ` "-resource `"$PSScriptRoot\includes\branding-resources\spwizimg-resources\setup-bg.png`"", ` "-mask IMAGE,517,1033" ` -NoNewWindow -Wait Remove-Item -Path "$ScratchDisk\tiny11\sources\spwizimg.dll" -Force | Out-Null Rename-Item -Path "$ScratchDisk\tiny11\sources\spwizimg.dll2" -NewName "spwizimg.dll" | Out-Null } # Add additional install.wim or install.esd files to the main install.wim Write-Host "Checking for additional install.wim or install.esd files..." $additionalWIM = Get-Item "$PSScriptRoot\includes\install.wim" -ErrorAction SilentlyContinue $additionalESD = Get-Item "$PSScriptRoot\includes\install.esd" -ErrorAction SilentlyContinue # Define the main install.wim path $mainWIM = "$ScratchDisk\tiny11\sources\install.wim" if ($additionalWIM) { Write-Host "Additional WIM file found: $($additionalWIM.FullName). Adding it to the main install.wim..." # Get all images from the additional WIM and add them $additionalImages = Get-WindowsImage -ImagePath $additionalWIM.FullName foreach ($imageInfo in $additionalImages) { $imageIndex = $imageInfo.ImageIndex $imageName = $imageInfo.ImageName Write-Host "Adding image $imageIndex`: $imageName from WIM file..." & 'dism' '/Export-Image' "/SourceImageFile:$($additionalWIM.FullName)" "/SourceIndex:$imageIndex" "/DestinationImageFile:$mainWIM" '/Compress:max' '/CheckIntegrity' } Write-Host "Successfully added all images from $($additionalWIM.FullName) to the main install.wim." } if ($additionalESD) { Write-Host "Additional ESD file found: $($additionalESD.FullName). Adding it to the main install.wim..." # Get all images from the additional ESD and add them $additionalImages = Get-WindowsImage -ImagePath $additionalESD.FullName foreach ($imageInfo in $additionalImages) { $imageIndex = $imageInfo.ImageIndex $imageName = $imageInfo.ImageName Write-Host "Adding image $imageIndex`: $imageName from ESD file..." & 'dism' '/Export-Image' "/SourceImageFile:$($additionalESD.FullName)" "/SourceIndex:$imageIndex" "/DestinationImageFile:$mainWIM" '/Compress:max' '/CheckIntegrity' } Write-Host "Successfully added all images from $($additionalESD.FullName) to the main install.wim." } if (-not $additionalWIM -and -not $additionalESD) { Write-Host "No additional WIM or ESD files found." } # convert the install.wim to install.esd Write-Host "Converting install.wim to install.esd..." # Get all image indexes from the install.wim $allImages = Get-WindowsImage -ImagePath "$ScratchDisk\tiny11\sources\install.wim" Write-Host "Found $($allImages.Count) image(s) in install.wim" # Export all images to install.esd using DISM.exe (since PowerShell DISM module doesn't support Recovery compression) $esdConvertOk = $true foreach ($imageInfo in $allImages) { $currentIndex = $imageInfo.ImageIndex $imageName = $imageInfo.ImageName Write-Host "Exporting image $currentIndex`: $imageName..." if ($currentIndex -eq $allImages[0].ImageIndex) { # First image - create new install.esd in the working directory & dism /English /Export-Image "/SourceImageFile:$ScratchDisk\tiny11\sources\install.wim" "/SourceIndex:$currentIndex" "/DestinationImageFile:$ScratchDisk\tiny11\sources\install.esd" /Compress:recovery /CheckIntegrity } else { # Subsequent images - append to existing install.esd & dism /English /Export-Image "/SourceImageFile:$ScratchDisk\tiny11\sources\install.wim" "/SourceIndex:$currentIndex" "/DestinationImageFile:$ScratchDisk\tiny11\sources\install.esd" /Compress:recovery /CheckIntegrity } if ($LASTEXITCODE -ne 0) { Write-Warning "ESD conversion failed (exit $LASTEXITCODE). Keeping install.wim and skipping ESD step." Remove-Item -Path "$ScratchDisk\tiny11\sources\install.esd" -Force -ErrorAction SilentlyContinue | Out-Null $esdConvertOk = $false break } } if ($esdConvertOk) { Remove-Item -Path "$ScratchDisk\tiny11\sources\install.wim" -Force | Out-Null Write-Host "All images converted from install.wim to install.esd successfully." } else { Write-Host "ESD conversion skipped. ISO will use install.wim (larger but functional)." } Write-Host "Creating ISO image..." # Get Windows ADK path from registry(following Visual Studio's winsdk.bat approach). $WinSDKPath = [Microsoft.Win32.Registry]::GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots", "KitsRoot10", $null) if ($null -eq $WinSDKPath) { $WinSDKPath = [Microsoft.Win32.Registry]::GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots", "KitsRoot10", $null) } if ($null -ne $WinSDKPath) { # Trim the following backslash for path concatenation. $WinSDKPath = $WinSDKPath.TrimEnd('\') $ADKDepTools = "$WinSDKPath\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture\Oscdimg" } $localOSCDIMGPath = "$PSScriptRoot\oscdimg.exe" if ((Test-Path variable:ADKDepTools) -and (Test-Path "$ADKDepTools\oscdimg.exe" -PathType leaf)) { Write-Host "Will be using oscdimg.exe from system ADK." $OSCDIMG = "$ADKDepTools\oscdimg.exe" } else { Write-Host "oscdimg.exe from system ADK not found. Will be using bundled oscdimg.exe." $url = "https://msdl.microsoft.com/download/symbols/oscdimg.exe/3D44737265000/oscdimg.exe" if (![System.IO.File]::Exists($localOSCDIMGPath)) { Write-Host "Downloading oscdimg.exe..." Invoke-WebRequest -Uri $url -OutFile $localOSCDIMGPath if ([System.IO.File]::Exists($localOSCDIMGPath)) { Write-Host "oscdimg.exe downloaded successfully." } else { Write-Error "Failed to download oscdimg.exe." exit 1 } } else { Write-Host "oscdimg.exe already exists locally." } $OSCDIMG = $localOSCDIMGPath } & "$OSCDIMG" "-lTiny11_$architecture" '-m' '-o' '-u2' '-udfver102' "-bootdata:2#p0,e,b$ScratchDisk\tiny11\boot\etfsboot.com#pEF,e,b$ScratchDisk\tiny11\efi\microsoft\boot\efisys.bin" "$ScratchDisk\tiny11" "$PSScriptRoot\tiny11.iso" # Finishing up Write-Host "Creation completed! Performing Cleanup..." Remove-Item -Path "$ScratchDisk\tiny11" -Recurse -Force | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir" -Recurse -Force | Out-Null # Unmount ISO if we auto-mounted it if ($mountedISO) { Write-Host "Unmounting ISO: $mountedISO" Dismount-DiskImage -ImagePath $mountedISO -ErrorAction SilentlyContinue | Out-Null Write-Host "ISO unmounted." } # Stop the transcript Stop-Transcript exit