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.
This commit is contained in:
@@ -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.
|
||||
|
||||
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
|
||||
|
||||
For more detailed information, see the documentation in the `/docs/` folder:
|
||||
|
||||
@@ -9,7 +9,8 @@ param (
|
||||
[string]$imageindex,
|
||||
[ValidateSet("10", "11", "auto")]
|
||||
[string]$WindowsVersion = "auto",
|
||||
[switch]$UseSetupTemplate
|
||||
[switch]$UseSetupTemplate,
|
||||
[switch]$IgnoreSecBoot
|
||||
)
|
||||
|
||||
# Check if PowerShell execution is Restricted or AllSigned or Undefined
|
||||
@@ -49,6 +50,7 @@ if (! $myWindowsPrincipal.IsInRole($adminRole)) {
|
||||
$argString += " -WindowsVersion `"$WindowsVersion`""
|
||||
}
|
||||
if ($UseSetupTemplate) { $argString += " -UseSetupTemplate" }
|
||||
if ($IgnoreSecBoot) { $argString += " -IgnoreSecBoot" }
|
||||
$newProcess.Arguments = $argString;
|
||||
$newProcess.Verb = "runas";
|
||||
[System.Diagnostics.Process]::Start($newProcess);
|
||||
@@ -472,6 +474,9 @@ if ($imageindex) {
|
||||
if ($UseSetupTemplate) {
|
||||
$argumentList += "-UseSetupTemplate"
|
||||
}
|
||||
if ($IgnoreSecBoot) {
|
||||
$argumentList += "-IgnoreSecBoot"
|
||||
}
|
||||
|
||||
# Start the appropriate maker script
|
||||
try {
|
||||
|
||||
@@ -50,7 +50,13 @@ function Get-RemotePackage {
|
||||
|
||||
if (-not (Test-Path $dest)) {
|
||||
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
|
||||
@@ -290,6 +296,9 @@ else {
|
||||
}
|
||||
|
||||
$mainAppPath = Get-RemotePackage $selectedFile.url
|
||||
if (-not $mainAppPath) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
default {
|
||||
|
||||
@@ -17,7 +17,7 @@ if (-not (Test-Path -Path $logPath)) {
|
||||
|
||||
function Get-ContentFromUrl {
|
||||
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."
|
||||
@@ -93,4 +93,8 @@ Write-Output "Installing UWP UI Components for all users..."
|
||||
|
||||
#### 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\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
|
||||
if ($PSVersionTable.PSVersion.Major -ge 3) {
|
||||
# Use new variable syntax in PowerShell 3 and above
|
||||
$currentDir = $PSScriptRoot
|
||||
try {
|
||||
Start-Transcript -Path "$env:WINDIR\OEM\setup\scripts\setup-user.log" -Append
|
||||
}
|
||||
else {
|
||||
# Use old variable syntax in Windows PowerShell 3 and below
|
||||
$currentDir = (Get-Item .).FullName
|
||||
catch {
|
||||
# Transcript failing to start must not block the rest of setup
|
||||
}
|
||||
|
||||
# Import script-helper.ps1
|
||||
. "$currentDir\..\..\scripts\script-helper.ps1"
|
||||
try {
|
||||
# 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
|
||||
if ((Get-WindowsVersionDetails).LicenseStatus -ne "Licensed") {
|
||||
& ([ScriptBlock]::Create((Invoke-RestMethod https://get.activated.win))) /HWID /HWID-NoEditionChange
|
||||
}
|
||||
# Import script-helper.ps1
|
||||
. "$currentDir\..\..\scripts\script-helper.ps1"
|
||||
|
||||
# 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 ####
|
||||
$cursorkey = "HKCU:\Control Panel\Cursors"
|
||||
@@ -88,4 +103,21 @@ if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
|
||||
& "$windowsDrive\Windows\OEM\setup\scripts\install-apps-user.ps1"
|
||||
|
||||
## 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
|
||||
}
|
||||
|
||||
#### 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) ####
|
||||
Write-Output "Installing oxmc-servers root certificate..."
|
||||
& "$windowsDrive\Windows\OEM\scripts\install-certs.ps1" -Silent
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[MRU List]
|
||||
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=
|
||||
MRU4=
|
||||
MRU5=
|
||||
|
||||
@@ -16,8 +16,10 @@ param(
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$PfxPassword = "",
|
||||
|
||||
[switch]$UseLegacySizes
|
||||
|
||||
[switch]$UseLegacySizes,
|
||||
|
||||
[switch]$IgnoreSecBoot
|
||||
)
|
||||
|
||||
#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 Resize-Bitmap {
|
||||
param(
|
||||
@@ -412,6 +422,12 @@ try {
|
||||
$signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath `
|
||||
-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 {
|
||||
Write-Log "No certificate specified. Skipping code signing." -Color "Yellow"
|
||||
}
|
||||
@@ -439,7 +455,16 @@ try {
|
||||
Write-Host "[!] File is NOT signed" -ForegroundColor Yellow
|
||||
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
|
||||
$FinallDLL = Join-Path $PSScriptRoot "bootres_modified.dll"
|
||||
Copy-Item -Path $outputDll -Destination $FinallDLL -Force
|
||||
|
||||
@@ -6,6 +6,36 @@ param(
|
||||
|
||||
$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)) {
|
||||
Write-Error "ISO not found: $IsoPath"
|
||||
exit 1
|
||||
@@ -81,18 +111,31 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
# Replace autounattend.xml
|
||||
$newXml = "$projectRoot\includes\autounattend-win10.xml"
|
||||
# Detect Windows version so we inject the matching autounattend variant
|
||||
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)) {
|
||||
Write-Error "autounattend-win10.xml not found at: $newXml"
|
||||
Write-Error "autounattend-win$detectedVersion.xml not found at: $newXml"
|
||||
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
|
||||
|
||||
# Detect label from ISO filename
|
||||
# Detect label from ISO filename, tagged with the detected version
|
||||
$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"
|
||||
$bootEfi = "$tempDir\efi\microsoft\boot\efisys.bin"
|
||||
|
||||
+71
-7
@@ -5,7 +5,8 @@ param (
|
||||
[ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')]
|
||||
[string]$ScratchDisk,
|
||||
[string]$imageindex,
|
||||
[switch]$UseSetupTemplate
|
||||
[switch]$UseSetupTemplate,
|
||||
[switch]$IgnoreSecBoot
|
||||
)
|
||||
|
||||
$needchange = @("AllSigned", "Restricted", "Undefined")
|
||||
@@ -60,6 +61,7 @@ if (-not $ScratchDisk) {
|
||||
}
|
||||
}
|
||||
Write-Output "Scratch disk set to $ScratchDisk"
|
||||
$hostArchitecture = $Env:PROCESSOR_ARCHITECTURE
|
||||
$setupMediaTemplatePath = "$PSScriptRoot\setup-media-template"
|
||||
New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny10\sources" >null
|
||||
$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\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\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:"
|
||||
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
|
||||
}
|
||||
|
||||
# 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..."
|
||||
& '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 '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"
|
||||
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 "Unmounting Registry..."
|
||||
@@ -451,13 +478,50 @@ Write-Host "Would you like to create an ISO? (y/n)"
|
||||
$iso = Read-Host
|
||||
|
||||
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..."
|
||||
& "$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"
|
||||
Write-Host "ISO created successfully!"
|
||||
} else {
|
||||
Write-Host "Windows ADK is not installed. Cannot create ISO."
|
||||
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" '-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..."
|
||||
|
||||
+23
-1
@@ -6,7 +6,8 @@ param (
|
||||
[string]$ScratchDisk,
|
||||
[string]$windowsisopath,
|
||||
[string]$imageindex,
|
||||
[switch]$UseSetupTemplate
|
||||
[switch]$UseSetupTemplate,
|
||||
[switch]$IgnoreSecBoot
|
||||
)
|
||||
|
||||
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\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
|
||||
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:"
|
||||
& '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
|
||||
@@ -796,6 +801,20 @@ Write-Host "Cleaning up image..."
|
||||
dism.exe /Image:$ScratchDisk\scratchdir /Cleanup-Image /StartComponentCleanup /ResetBase
|
||||
Write-Host "Cleanup complete."
|
||||
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..."
|
||||
Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save
|
||||
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' '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
|
||||
if ($IgnoreSecBoot) {
|
||||
& 'reg' 'add' 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'IgnoreSecBootBootRes' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||
}
|
||||
Write-Host "Tweaking complete! Unmounting Registry..."
|
||||
$regKey.Close()
|
||||
reg unload HKLM\zCOMPONENTS | Out-Null
|
||||
|
||||
+23
-1
@@ -5,7 +5,8 @@ param (
|
||||
[ValidatePattern('^[c-zC-Z]:?$|^[a-zA-Z]:\\.*$')]
|
||||
[string]$ScratchDisk,
|
||||
[string]$imageindex,
|
||||
[switch]$UseSetupTemplate
|
||||
[switch]$UseSetupTemplate,
|
||||
[switch]$IgnoreSecBoot
|
||||
)
|
||||
|
||||
$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 '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"
|
||||
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:"
|
||||
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"
|
||||
@@ -780,6 +784,21 @@ Write-Host "Cleaning up image..."
|
||||
& 'dism' '/English' "/image:$ScratchDisk\scratchdir" '/Cleanup-Image' '/StartComponentCleanup' '/ResetBase' >null
|
||||
Write-Host "Cleanup complete."
|
||||
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..."
|
||||
& 'dism' '/English' '/unmount-image' "/mountdir:$ScratchDisk\scratchdir" '/commit'
|
||||
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 '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"
|
||||
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"
|
||||
Write-Host "Tweaking complete!"
|
||||
Write-Host "Unmounting Registry..."
|
||||
|
||||
+1168
-183
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user