Compare commits

1 Commits
Author SHA1 Message Date
oxmc d38cd32b82 Fix registry ownership/ACL and hang bugs in tiny11maker.ps1, plus build/setup script updates
Fixes several offline-hive build failures: TrustedInstaller-owned keys
(WindowsRuntime\ActivatableClassId, Explorer\Advanced, System\GameConfigStore, Search
SystemIndex) denying writes even to admin-owned processes, a PowerShell 5.1 quirk that drops
empty-string reg.exe arguments and can hang the build on a silent overwrite prompt, a
registry-handle leak that left hives locked and cascaded into DISM cleanup failures, and
relaxed the post-ResetBase health gate to accept 'Repairable' (only abort on
'NonRepairable') since ResetBase makes full repair impossible anyway - documented that
repairing the installed OS needs the original stock ISO, not the tweaked output. Also
rolls in in-progress updates to the other maker scripts and OEM setup/first-boot scripts.
2026-07-31 06:09:58 -07:00
16 changed files with 1477 additions and 220 deletions
+6
View File
@@ -197,6 +197,12 @@ The MultiStaller tool provides flexible, configuration-driven software installat
3. If you are using this script on arm64, you might see a glimpse of an error while running the script. This is caused by the fact that the arm64 image doesn't have OneDriveSetup.exe included in the System32 folder. 3. If you are using this script on arm64, you might see a glimpse of an error while running the script. This is caused by the fact that the arm64 image doesn't have OneDriveSetup.exe included in the System32 folder.
4. **DISM/SFC repair after install won't work against the tweaked media.** The build runs `/Cleanup-Image /StartComponentCleanup /ResetBase` to shrink the component store, which permanently deletes superseded package versions from the image. If your installed system's component store ever needs repair (`DISM /Online /Cleanup-Image /RestoreHealth` or `sfc /scannow`), pointing `/Source` at the *tweaked* `install.wim`/`install.esd`/ISO will not help - those files are gone from every copy of that build, not just the one you're repairing. Keep the **original, untouched stock Windows ISO** you downloaded from Microsoft around, and use that as the repair source instead, e.g.:
```powershell
DISM /Online /Cleanup-Image /RestoreHealth /Source:WIM:D:\sources\install.wim:1 /LimitAccess
```
(where `D:` is your mounted *original* ISO, not the tiny11 output.)
## Documentation ## Documentation
For more detailed information, see the documentation in the `/docs/` folder: For more detailed information, see the documentation in the `/docs/` folder:
+6 -1
View File
@@ -9,7 +9,8 @@ param (
[string]$imageindex, [string]$imageindex,
[ValidateSet("10", "11", "auto")] [ValidateSet("10", "11", "auto")]
[string]$WindowsVersion = "auto", [string]$WindowsVersion = "auto",
[switch]$UseSetupTemplate [switch]$UseSetupTemplate,
[switch]$IgnoreSecBoot
) )
# Check if PowerShell execution is Restricted or AllSigned or Undefined # Check if PowerShell execution is Restricted or AllSigned or Undefined
@@ -49,6 +50,7 @@ if (! $myWindowsPrincipal.IsInRole($adminRole)) {
$argString += " -WindowsVersion `"$WindowsVersion`"" $argString += " -WindowsVersion `"$WindowsVersion`""
} }
if ($UseSetupTemplate) { $argString += " -UseSetupTemplate" } if ($UseSetupTemplate) { $argString += " -UseSetupTemplate" }
if ($IgnoreSecBoot) { $argString += " -IgnoreSecBoot" }
$newProcess.Arguments = $argString; $newProcess.Arguments = $argString;
$newProcess.Verb = "runas"; $newProcess.Verb = "runas";
[System.Diagnostics.Process]::Start($newProcess); [System.Diagnostics.Process]::Start($newProcess);
@@ -472,6 +474,9 @@ if ($imageindex) {
if ($UseSetupTemplate) { if ($UseSetupTemplate) {
$argumentList += "-UseSetupTemplate" $argumentList += "-UseSetupTemplate"
} }
if ($IgnoreSecBoot) {
$argumentList += "-IgnoreSecBoot"
}
# Start the appropriate maker script # Start the appropriate maker script
try { try {
@@ -50,7 +50,13 @@ function Get-RemotePackage {
if (-not (Test-Path $dest)) { if (-not (Test-Path $dest)) {
Write-Host "Downloading $fileName..." -ForegroundColor Cyan Write-Host "Downloading $fileName..." -ForegroundColor Cyan
Invoke-WebRequest -Uri $Url -OutFile $dest -UseBasicParsing try {
Invoke-WebRequest -Uri $Url -OutFile $dest -UseBasicParsing -TimeoutSec 15
}
catch {
Write-Host "Download failed or timed out for $Url : $($_.Exception.Message)" -ForegroundColor Red
return $null
}
} }
return $dest return $dest
@@ -290,6 +296,9 @@ else {
} }
$mainAppPath = Get-RemotePackage $selectedFile.url $mainAppPath = Get-RemotePackage $selectedFile.url
if (-not $mainAppPath) {
continue
}
} }
default { default {
@@ -17,7 +17,7 @@ if (-not (Test-Path -Path $logPath)) {
function Get-ContentFromUrl { function Get-ContentFromUrl {
param([string]$url) param([string]$url)
(Invoke-WebRequest -Uri $url -UseBasicParsing -ErrorAction Stop).Content (Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 15 -ErrorAction Stop).Content
} }
# ========================= # =========================
@@ -0,0 +1,37 @@
# Check PowerShell version for use in path
if ($PSVersionTable.PSVersion.Major -ge 3) {
$currentDir = $PSScriptRoot
}
else {
$currentDir = (Get-Item .).FullName
}
# Only run if the maker script flagged this build with -IgnoreSecBoot
$labConfigPath = "HKLM:\SYSTEM\Setup\LabConfig"
$flag = Get-ItemProperty -Path $labConfigPath -Name "IgnoreSecBootBootRes" -ErrorAction SilentlyContinue
if (-not $flag -or $flag.IgnoreSecBootBootRes -ne 1) {
return
}
Write-Output "IgnoreSecBootBootRes flag set - checking Secure Boot state before touching BCD..."
# Confirm-SecureBootUEFI throws on legacy BIOS / non-UEFI firmware - no Secure Boot to worry about there
$secureBootOn = $false
try {
$secureBootOn = Confirm-SecureBootUEFI
}
catch {
Write-Output "Confirm-SecureBootUEFI unavailable (legacy BIOS/non-UEFI) - Secure Boot not applicable, proceeding."
$secureBootOn = $false
}
if ($secureBootOn) {
Write-Warning "Secure Boot is ENABLED - skipping testsigning/nointegritychecks. Windows ignores both settings while Secure Boot is on, and forcing them here would do nothing but risk an inconsistent BCD. Disable Secure Boot in UEFI firmware, then re-run this script (`"$PSCommandPath`") manually to apply the settings - it only runs automatically once, during setup."
return
}
& bcdedit /set '{current}' testsigning on | Out-Null
& bcdedit /set '{current}' nointegritychecks on | Out-Null
Write-Output "testsigning/nointegritychecks enabled - Secure Boot was off, so this should take effect on next reboot."
@@ -94,3 +94,7 @@ Write-Output "Installing UWP UI Components for all users..."
#### Install Normal Apps (Machine wide) #### #### Install Normal Apps (Machine wide) ####
Start-Process -FilePath "$windowsDrive\Windows\OEM\MultiStaller.exe" -ArgumentList "--config", "$windowsDrive\Windows\OEM\setup\apps-machine-wide.yml" -WindowStyle Maximized -Wait Start-Process -FilePath "$windowsDrive\Windows\OEM\MultiStaller.exe" -ArgumentList "--config", "$windowsDrive\Windows\OEM\setup\apps-machine-wide.yml" -WindowStyle Maximized -Wait
Start-Process -FilePath "$windowsDrive\Windows\OEM\ChromeMassInstaller.exe" -ArgumentList "--no_pref" -Wait Start-Process -FilePath "$windowsDrive\Windows\OEM\ChromeMassInstaller.exe" -ArgumentList "--no_pref" -Wait
# Install other miscellaneous applications (mostly for user convenience)
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$windowsDrive\Windows\OEM\apps\other\Monitarian-4.14.0.msi`" /quiet /norestart" -Wait -PassThru
Start-Process -FilePath "$windowsDrive\Windows\OEM\apps\other\ShareX-19.0.2-setup.exe" -ArgumentList "/S" -Wait
@@ -1,20 +1,35 @@
# Check PowerShell version for use in path try {
if ($PSVersionTable.PSVersion.Major -ge 3) { Start-Transcript -Path "$env:WINDIR\OEM\setup\scripts\setup-user.log" -Append
# Use new variable syntax in PowerShell 3 and above
$currentDir = $PSScriptRoot
} }
else { catch {
# Use old variable syntax in Windows PowerShell 3 and below # Transcript failing to start must not block the rest of setup
$currentDir = (Get-Item .).FullName
} }
# Import script-helper.ps1 try {
. "$currentDir\..\..\scripts\script-helper.ps1" # Check PowerShell version for use in path
if ($PSVersionTable.PSVersion.Major -ge 3) {
# Use new variable syntax in PowerShell 3 and above
$currentDir = $PSScriptRoot
}
else {
# Use old variable syntax in Windows PowerShell 3 and below
$currentDir = (Get-Item .).FullName
}
# Before doing ANYTHING, check if windwos is activated # Import script-helper.ps1
if ((Get-WindowsVersionDetails).LicenseStatus -ne "Licensed") { . "$currentDir\..\..\scripts\script-helper.ps1"
& ([ScriptBlock]::Create((Invoke-RestMethod https://get.activated.win))) /HWID /HWID-NoEditionChange
} # Before doing ANYTHING, check if windows is activated
try {
if ((Get-WindowsVersionDetails).LicenseStatus -ne "Licensed") {
Write-Output "Windows not licensed - fetching activation script from get.activated.win..."
$activationScript = Invoke-RestMethod -Uri "https://get.activated.win" -TimeoutSec 15 -UseBasicParsing
& ([ScriptBlock]::Create($activationScript)) /HWID /HWID-NoEditionChange
}
}
catch {
Write-Warning "Activation step failed or timed out, continuing setup without activation: $($_.Exception.Message)"
}
#### Set cursor theme to Posys Cursor #### #### Set cursor theme to Posys Cursor ####
$cursorkey = "HKCU:\Control Panel\Cursors" $cursorkey = "HKCU:\Control Panel\Cursors"
@@ -89,3 +104,20 @@ if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
## Install apps (modern windows apps, such as: store apps, winget, appx, msix, etc [appx/msix/others can be downloaded from url]) ## Install apps (modern windows apps, such as: store apps, winget, appx, msix, etc [appx/msix/others can be downloaded from url])
& "$windowsDrive\Windows\OEM\scripts\install-win-apps.ps1" & "$windowsDrive\Windows\OEM\scripts\install-win-apps.ps1"
}
catch {
Write-Error "setup-user.ps1 failed: $($_.Exception.Message)"
Write-Output $_.ScriptStackTrace
}
finally {
try {
Stop-Transcript
}
catch {
# Nothing to stop, ignore
}
}
# Always exit 0 - a failure here must be logged and diagnosed via setup-user.log,
# not surfaced as an OOBE error dialog or left to hang FirstLogonCommands.
exit 0
@@ -22,6 +22,9 @@ if ($appsRoot -and (Test-Path $bootcampPath)) {
& $bootcampPath & $bootcampPath
} }
#### Apply custom bootres.dll Secure Boot compatibility settings (only runs if flagged at build time) ####
& "$currentDir\enable-custom-bootres.ps1"
#### Install oxmc-servers Root Certificate (required for system apps) #### #### Install oxmc-servers Root Certificate (required for system apps) ####
Write-Output "Installing oxmc-servers root certificate..." Write-Output "Installing oxmc-servers root certificate..."
& "$windowsDrive\Windows\OEM\scripts\install-certs.ps1" -Silent & "$windowsDrive\Windows\OEM\scripts\install-certs.ps1" -Silent
+1 -1
View File
@@ -1,6 +1,6 @@
[MRU List] [MRU List]
MRU1=C:\Users\oxmc\Documents\Github\CustomTiny11\working\tiny11\sources\spwizimg.dll MRU1=C:\Users\oxmc\Documents\Github\CustomTiny11\working\tiny11\sources\spwizimg.dll
MRU2=C:\Users\oxmc\Documents\Github\CustomTiny11\working\tiny10\sources\spwizimg.dll MRU2=
MRU3= MRU3=
MRU4= MRU4=
MRU5= MRU5=
+26 -1
View File
@@ -17,7 +17,9 @@ param(
[Parameter(Mandatory = $false)] [Parameter(Mandatory = $false)]
[string]$PfxPassword = "", [string]$PfxPassword = "",
[switch]$UseLegacySizes [switch]$UseLegacySizes,
[switch]$IgnoreSecBoot
) )
#Requires -RunAsAdministrator #Requires -RunAsAdministrator
@@ -253,6 +255,14 @@ function Sign-FileWithCertificate {
} }
} }
# Function to create a throwaway self-signed code-signing cert (IgnoreSecBoot path only)
function New-ThrowawaySigningCert {
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=CustomTiny11 IgnoreSecBoot" `
-CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeyUsage DigitalSignature `
-NotAfter (Get-Date).AddYears(5)
return $cert
}
# Function to resize bitmap # Function to resize bitmap
function Resize-Bitmap { function Resize-Bitmap {
param( param(
@@ -412,6 +422,12 @@ try {
$signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath ` $signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath `
-CertificateThumbprint $CertificateThumbprint -PfxPath $PfxPath -PfxPassword $PfxPassword -CertificateThumbprint $CertificateThumbprint -PfxPath $PfxPath -PfxPassword $PfxPassword
} }
elseif ($IgnoreSecBoot) {
Write-Log "IgnoreSecBoot set and no certificate given - generating throwaway self-signed cert..." -Color "Yellow"
$throwawayCert = New-ThrowawaySigningCert
$signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath `
-CertificateThumbprint $throwawayCert.Thumbprint
}
else { else {
Write-Log "No certificate specified. Skipping code signing." -Color "Yellow" Write-Log "No certificate specified. Skipping code signing." -Color "Yellow"
} }
@@ -440,6 +456,15 @@ try {
Write-Host " Requires Test Signing mode or Secure Boot disabled" -ForegroundColor Gray Write-Host " Requires Test Signing mode or Secure Boot disabled" -ForegroundColor Gray
} }
if ($IgnoreSecBoot) {
Write-Host ""
Write-Host "[IgnoreSecBoot] Signed with throwaway cert (not Microsoft-trusted)." -ForegroundColor Yellow
Write-Host " Build the image with -IgnoreSecBoot on the maker script too - it flags first boot" -ForegroundColor Gray
Write-Host " to run 'bcdedit /set testsigning on' and 'bcdedit /set nointegritychecks on'." -ForegroundColor Gray
Write-Host " Those settings are IGNORED by Windows while Secure Boot is on in firmware." -ForegroundColor Gray
Write-Host " Secure Boot must be disabled manually in UEFI setup for this to boot." -ForegroundColor Gray
}
# Copy final DLL to script directory # Copy final DLL to script directory
$FinallDLL = Join-Path $PSScriptRoot "bootres_modified.dll" $FinallDLL = Join-Path $PSScriptRoot "bootres_modified.dll"
Copy-Item -Path $outputDll -Destination $FinallDLL -Force Copy-Item -Path $outputDll -Destination $FinallDLL -Force
+49 -6
View File
@@ -6,6 +6,36 @@ param(
$projectRoot = (Resolve-Path "$PSScriptRoot\..\..") $projectRoot = (Resolve-Path "$PSScriptRoot\..\..")
# Detect Windows 10 vs 11 from install.wim/install.esd so the right autounattend variant gets injected
function Get-WindowsVersionFromMedia {
param([string]$MediaRoot)
$srcBase = $MediaRoot
if (-not (Test-Path "$srcBase\sources\install.wim") -and -not (Test-Path "$srcBase\sources\install.esd") -and (Test-Path "$srcBase\x64\sources")) {
$srcBase = "$srcBase\x64"
}
$imagePath = if (Test-Path "$srcBase\sources\install.wim") { "$srcBase\sources\install.wim" }
elseif (Test-Path "$srcBase\sources\install.esd") { "$srcBase\sources\install.esd" }
else { $null }
if (-not $imagePath) { return $null }
try {
$imgInfo = Get-WindowsImage -ImagePath $imagePath -Index 1
$parts = $imgInfo.Version.Split('.')
if ($parts.Count -ge 3) {
$build = [int]$parts[2]
if ($build -ge 22000) { return "11" }
elseif ($build -ge 10240) { return "10" }
}
}
catch {
Write-Warning "Could not read Windows version from media: $($_.Exception.Message)"
}
return $null
}
if (-not (Test-Path $IsoPath)) { if (-not (Test-Path $IsoPath)) {
Write-Error "ISO not found: $IsoPath" Write-Error "ISO not found: $IsoPath"
exit 1 exit 1
@@ -81,18 +111,31 @@ try {
} }
} }
# Replace autounattend.xml # Detect Windows version so we inject the matching autounattend variant
$newXml = "$projectRoot\includes\autounattend-win10.xml" Write-Host "Detecting Windows version from media..."
$detectedVersion = Get-WindowsVersionFromMedia -MediaRoot $tempDir
if (-not $detectedVersion) {
Write-Host "Could not automatically detect Windows version from media."
do {
$detectedVersion = Read-Host "Enter Windows version (10 or 11)"
} while ($detectedVersion -notin @("10", "11"))
}
else {
Write-Host "Detected Windows $detectedVersion media."
}
# Replace autounattend.xml with the version-matched variant
$newXml = "$projectRoot\includes\autounattend-win$detectedVersion.xml"
if (-not (Test-Path $newXml)) { if (-not (Test-Path $newXml)) {
Write-Error "autounattend-win10.xml not found at: $newXml" Write-Error "autounattend-win$detectedVersion.xml not found at: $newXml"
exit 1 exit 1
} }
Write-Host "Replacing autounattend.xml..." Write-Host "Replacing autounattend.xml with autounattend-win$detectedVersion.xml..."
Copy-Item -Path $newXml -Destination "$tempDir\autounattend.xml" -Force Copy-Item -Path $newXml -Destination "$tempDir\autounattend.xml" -Force
# Detect label from ISO filename # Detect label from ISO filename, tagged with the detected version
$isoName = [System.IO.Path]::GetFileNameWithoutExtension($IsoPath) $isoName = [System.IO.Path]::GetFileNameWithoutExtension($IsoPath)
$label = if ($isoName -match 'x86') { "Tiny10_x86" } else { "Tiny10_x64" } $label = if ($isoName -match 'x86') { "Tiny${detectedVersion}_x86" } else { "Tiny${detectedVersion}_x64" }
$bootEtfs = "$tempDir\boot\etfsboot.com" $bootEtfs = "$tempDir\boot\etfsboot.com"
$bootEfi = "$tempDir\efi\microsoft\boot\efisys.bin" $bootEfi = "$tempDir\efi\microsoft\boot\efisys.bin"
+71 -7
View File
@@ -5,7 +5,8 @@ param (
[ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')] [ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')]
[string]$ScratchDisk, [string]$ScratchDisk,
[string]$imageindex, [string]$imageindex,
[switch]$UseSetupTemplate [switch]$UseSetupTemplate,
[switch]$IgnoreSecBoot
) )
$needchange = @("AllSigned", "Restricted", "Undefined") $needchange = @("AllSigned", "Restricted", "Undefined")
@@ -60,6 +61,7 @@ if (-not $ScratchDisk) {
} }
} }
Write-Output "Scratch disk set to $ScratchDisk" Write-Output "Scratch disk set to $ScratchDisk"
$hostArchitecture = $Env:PROCESSOR_ARCHITECTURE
$setupMediaTemplatePath = "$PSScriptRoot\setup-media-template" $setupMediaTemplatePath = "$PSScriptRoot\setup-media-template"
New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny10\sources" >null New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny10\sources" >null
$DriveLetter = Read-Host "Please enter the drive letter for the Windows 10 image" $DriveLetter = Read-Host "Please enter the drive letter for the Windows 10 image"
@@ -247,6 +249,13 @@ Set-RegistryValue -KeyPath 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotif
Set-RegistryValue -KeyPath 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "Unsupported hardware notification SV2" Set-RegistryValue -KeyPath 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "Unsupported hardware notification SV2"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV1' -ValueType 'REG_DWORD' -ValueData '0' -Description "User unsupported hardware notification SV1" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV1' -ValueType 'REG_DWORD' -ValueData '0' -Description "User unsupported hardware notification SV1"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "User unsupported hardware notification SV2" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "User unsupported hardware notification SV2"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassCPUCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass CPU check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassRAMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass RAM check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassSecureBootCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass Secure Boot check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassStorageCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass storage check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassTPMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass TPM check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\MoSetup' -ValueName 'AllowUpgradesWithUnsupportedTPMOrCPU' -ValueType 'REG_DWORD' -ValueData '1' -Description "Allow upgrades with unsupported TPM or CPU"
Set-RegistryValue -KeyPath 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' -ValueName 'BypassNRO' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass network requirement in OOBE"
Write-Host "Disabling Sponsored Apps:" Write-Host "Disabling Sponsored Apps:"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'OemPreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "OEM pre-installed apps" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'OemPreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "OEM pre-installed apps"
@@ -376,6 +385,21 @@ if (Test-Path "$ScratchDisk\scratchdir\Windows\WinSxS_backup") {
Move-Item -Path "$ScratchDisk\scratchdir\Windows\WinSxS_backup" -Destination "$ScratchDisk\scratchdir\Windows\WinSxS" -Force Move-Item -Path "$ScratchDisk\scratchdir\Windows\WinSxS_backup" -Destination "$ScratchDisk\scratchdir\Windows\WinSxS" -Force
} }
# Verify the component store isn't corrupt before we capture it.
# Must run AFTER the WinSxS restore above - scanning while WinSxS is swapped out would
# always report corruption. /AnalyzeComponentStore is online-only (running OS) and only
# reports size/cleanup recommendations, not a healthy/unhealthy verdict - /ScanHealth is
# the offline-capable corruption check with an actual pass/fail result worth aborting on.
Write-Host "Verifying component store health before capture..."
$scanHealthOutput = & 'dism' '/English' "/image:$ScratchDisk\scratchdir" '/Cleanup-Image' '/ScanHealth'
if ($scanHealthOutput -notmatch 'No component store corruption detected') {
$scanHealthOutput | Write-Host
Write-Error "Component store health check failed - possible corruption detected. Aborting build - image was NOT captured."
& 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/discard' >null
exit 1
}
Write-Host "Component store is healthy."
Write-Host "Unmounting image..." Write-Host "Unmounting image..."
& 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/commit' & 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/commit'
@@ -414,6 +438,9 @@ Set-RegistryValue -KeyPath 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotif
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV1' -ValueType 'REG_DWORD' -ValueData '0' -Description "Setup image user unsupported hardware notification SV1" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV1' -ValueType 'REG_DWORD' -ValueData '0' -Description "Setup image user unsupported hardware notification SV1"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "Setup image user unsupported hardware notification SV2" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' -ValueName 'SV2' -ValueType 'REG_DWORD' -ValueData '0' -Description "Setup image user unsupported hardware notification SV2"
Set-RegistryValue -KeyPath 'HKEY_LOCAL_MACHINE\zSYSTEM\Setup' -ValueName 'CmdLine' -ValueType 'REG_SZ' -ValueData 'X:\sources\setup.exe' -Description "Setup command line" Set-RegistryValue -KeyPath 'HKEY_LOCAL_MACHINE\zSYSTEM\Setup' -ValueName 'CmdLine' -ValueType 'REG_SZ' -ValueData 'X:\sources\setup.exe' -Description "Setup command line"
if ($IgnoreSecBoot) {
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'IgnoreSecBootBootRes' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image flag first boot to enable testsigning/nointegritychecks for custom bootres.dll"
}
Write-Host "Tweaking complete!" Write-Host "Tweaking complete!"
Write-Host "Unmounting Registry..." Write-Host "Unmounting Registry..."
@@ -451,13 +478,50 @@ Write-Host "Would you like to create an ISO? (y/n)"
$iso = Read-Host $iso = Read-Host
if ($iso -eq 'y') { if ($iso -eq 'y') {
if (Test-Path "$env:ProgramFiles(x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe") { Write-Host "Creating ISO image..."
Write-Host "Creating ISO..." # Get Windows ADK path from registry (following Visual Studio's winsdk.bat approach).
& "$env:ProgramFiles(x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe" '-m' '-o' '-u2' '-udfver102' "-bootdata:2#p0,e,b$ScratchDisk\tiny10\boot\etfsboot.com#pEF,e,b$ScratchDisk\tiny10\efi\microsoft\boot\efisys.bin" "$ScratchDisk\tiny10" "$PSScriptRoot\tiny10core.iso" $WinSDKPath = [Microsoft.Win32.Registry]::GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots", "KitsRoot10", $null)
Write-Host "ISO created successfully!" if ($null -eq $WinSDKPath) {
} else { $WinSDKPath = [Microsoft.Win32.Registry]::GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots", "KitsRoot10", $null)
Write-Host "Windows ADK is not installed. Cannot create ISO."
} }
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" '-m' '-o' '-u2' '-udfver102' "-bootdata:2#p0,e,b$ScratchDisk\tiny10\boot\etfsboot.com#pEF,e,b$ScratchDisk\tiny10\efi\microsoft\boot\efisys.bin" "$ScratchDisk\tiny10" "$PSScriptRoot\tiny10core.iso"
Write-Host "ISO created successfully!"
} }
Write-Host "Performing Cleanup..." Write-Host "Performing Cleanup..."
+23 -1
View File
@@ -6,7 +6,8 @@ param (
[string]$ScratchDisk, [string]$ScratchDisk,
[string]$windowsisopath, [string]$windowsisopath,
[string]$imageindex, [string]$imageindex,
[switch]$UseSetupTemplate [switch]$UseSetupTemplate,
[switch]$IgnoreSecBoot
) )
if (-not $ScratchDisk) { if (-not $ScratchDisk) {
@@ -542,6 +543,10 @@ Write-Host "Bypassing system requirements(on the system image):"
& 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassTPMCheck' '/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\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 & 'reg' 'add' 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' '/v' 'BypassNRO' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
if ($IgnoreSecBoot) {
Write-Host "IgnoreSecBoot set: flagging image to enable testsigning/nointegritychecks on first boot..."
& 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'IgnoreSecBootBootRes' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
}
Write-Host "Disabling Sponsored Apps:" 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' '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' 'PreInstalledAppsEnabled' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
@@ -796,6 +801,20 @@ Write-Host "Cleaning up image..."
dism.exe /Image:$ScratchDisk\scratchdir /Cleanup-Image /StartComponentCleanup /ResetBase dism.exe /Image:$ScratchDisk\scratchdir /Cleanup-Image /StartComponentCleanup /ResetBase
Write-Host "Cleanup complete." Write-Host "Cleanup complete."
Write-Host ' ' Write-Host ' '
# Verify the component store isn't corrupt before we capture it.
# /AnalyzeComponentStore is online-only (running OS) and only reports size/cleanup
# recommendations, not a healthy/unhealthy verdict - /ScanHealth is the offline-capable
# corruption check with an actual pass/fail result worth aborting the build on.
Write-Host "Verifying component store health before capture..."
$healthCheck = Repair-WindowsImage -Path $ScratchDisk\scratchdir -ScanHealth
if ($healthCheck.ImageHealthState -ne 'Healthy') {
Write-Error "Component store health check failed (state: $($healthCheck.ImageHealthState)). Aborting build - image was NOT captured."
Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Discard | Out-Null
exit 1
}
Write-Host "Component store is healthy."
Write-Host "Unmounting image..." Write-Host "Unmounting image..."
Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save
Write-Host "Exporting image..." Write-Host "Exporting image..."
@@ -828,6 +847,9 @@ Write-Host "Bypassing system requirements(on the setup image)..."
& 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassStorageCheck' '/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\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\zSYSTEM\Setup\MoSetup' '/v' 'AllowUpgradesWithUnsupportedTPMOrCPU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
if ($IgnoreSecBoot) {
& 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'IgnoreSecBootBootRes' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
}
Write-Host "Tweaking complete! Unmounting Registry..." Write-Host "Tweaking complete! Unmounting Registry..."
$regKey.Close() $regKey.Close()
reg unload HKLM\zCOMPONENTS | Out-Null reg unload HKLM\zCOMPONENTS | Out-Null
+23 -1
View File
@@ -5,7 +5,8 @@ param (
[ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')] [ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')]
[string]$ScratchDisk, [string]$ScratchDisk,
[string]$imageindex, [string]$imageindex,
[switch]$UseSetupTemplate [switch]$UseSetupTemplate,
[switch]$IgnoreSecBoot
) )
$needchange = @("AllSigned", "Restricted", "Undefined") $needchange = @("AllSigned", "Restricted", "Undefined")
@@ -421,6 +422,9 @@ Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassSecu
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassStorageCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass storage check" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassStorageCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass storage check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassTPMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass TPM check" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassTPMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Bypass TPM check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\MoSetup' -ValueName 'AllowUpgradesWithUnsupportedTPMOrCPU' -ValueType 'REG_DWORD' -ValueData '1' -Description "Allow upgrades with unsupported TPM or CPU" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\MoSetup' -ValueName 'AllowUpgradesWithUnsupportedTPMOrCPU' -ValueType 'REG_DWORD' -ValueData '1' -Description "Allow upgrades with unsupported TPM or CPU"
if ($IgnoreSecBoot) {
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'IgnoreSecBootBootRes' -ValueType 'REG_DWORD' -ValueData '1' -Description "Flag first boot to enable testsigning/nointegritychecks for custom bootres.dll"
}
Write-Host "Disabling Sponsored Apps:" Write-Host "Disabling Sponsored Apps:"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'OemPreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "OEM pre-installed apps" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'OemPreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "OEM pre-installed apps"
Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'PreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "Pre-installed apps" Set-RegistryValue -KeyPath 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' -ValueName 'PreInstalledAppsEnabled' -ValueType 'REG_DWORD' -ValueData '0' -Description "Pre-installed apps"
@@ -780,6 +784,21 @@ Write-Host "Cleaning up image..."
& 'dism' '/English' "/image:$ScratchDisk\scratchdir" '/Cleanup-Image' '/StartComponentCleanup' '/ResetBase' >null & 'dism' '/English' "/image:$ScratchDisk\scratchdir" '/Cleanup-Image' '/StartComponentCleanup' '/ResetBase' >null
Write-Host "Cleanup complete." Write-Host "Cleanup complete."
Write-Host ' ' Write-Host ' '
# Verify the component store isn't corrupt before we capture it.
# /AnalyzeComponentStore is online-only (running OS) and only reports size/cleanup
# recommendations, not a healthy/unhealthy verdict - /ScanHealth is the offline-capable
# corruption check with an actual pass/fail result worth aborting the build on.
Write-Host "Verifying component store health before capture..."
$scanHealthOutput = & 'dism' '/English' "/image:$ScratchDisk\scratchdir" '/Cleanup-Image' '/ScanHealth'
if ($scanHealthOutput -notmatch 'No component store corruption detected') {
$scanHealthOutput | Write-Host
Write-Error "Component store health check failed - possible corruption detected. Aborting build - image was NOT captured."
& 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/discard' >null
exit 1
}
Write-Host "Component store is healthy."
Write-Host "Unmounting image..." Write-Host "Unmounting image..."
& 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/commit' & 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/commit'
Write-Host "Exporting image..." Write-Host "Exporting image..."
@@ -812,6 +831,9 @@ Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassSecu
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassStorageCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image bypass storage check" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassStorageCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image bypass storage check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassTPMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image bypass TPM check" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'BypassTPMCheck' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image bypass TPM check"
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\MoSetup' -ValueName 'AllowUpgradesWithUnsupportedTPMOrCPU' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image allow upgrades with unsupported TPM or CPU" Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\MoSetup' -ValueName 'AllowUpgradesWithUnsupportedTPMOrCPU' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image allow upgrades with unsupported TPM or CPU"
if ($IgnoreSecBoot) {
Set-RegistryValue -KeyPath 'HKLM\zSYSTEM\Setup\LabConfig' -ValueName 'IgnoreSecBootBootRes' -ValueType 'REG_DWORD' -ValueData '1' -Description "Setup image flag first boot to enable testsigning/nointegritychecks for custom bootres.dll"
}
Set-RegistryValue -KeyPath 'HKEY_LOCAL_MACHINE\zSYSTEM\Setup' -ValueName 'CmdLine' -ValueType 'REG_SZ' -ValueData 'X:\sources\setup.exe' -Description "Setup command line" Set-RegistryValue -KeyPath 'HKEY_LOCAL_MACHINE\zSYSTEM\Setup' -ValueName 'CmdLine' -ValueType 'REG_SZ' -ValueData 'X:\sources\setup.exe' -Description "Setup command line"
Write-Host "Tweaking complete!" Write-Host "Tweaking complete!"
Write-Host "Unmounting Registry..." Write-Host "Unmounting Registry..."
+1242 -257
View File
File diff suppressed because it is too large Load Diff