diff --git a/functions/private/Copy-Files.ps1 b/functions/microwin/Copy-Files.ps1 similarity index 100% rename from functions/private/Copy-Files.ps1 rename to functions/microwin/Copy-Files.ps1 diff --git a/functions/microwin/Invoke-Microwin.ps1 b/functions/microwin/Invoke-Microwin.ps1 index c9e7b8ff..75a69009 100644 --- a/functions/microwin/Invoke-Microwin.ps1 +++ b/functions/microwin/Invoke-Microwin.ps1 @@ -54,14 +54,9 @@ public class PowerManagement { $index = $sync.MicrowinWindowsFlavors.SelectedValue.Split(":")[0].Trim() Write-Host "Index chosen: '$index' from $($sync.MicrowinWindowsFlavors.SelectedValue)" - $copyToUSB = $sync.WPFMicrowinCopyToUsb.IsChecked $injectDrivers = $sync.MicrowinInjectDrivers.IsChecked $importDrivers = $sync.MicrowinImportDrivers.IsChecked - $WPBT = $sync.MicroWinWPBT.IsChecked - $unsupported = $sync.MicroWinUnsupported.IsChecked - $skipFla = $sync.MicroWinNoFLA.IsChecked - $importVirtIO = $sync.MicrowinCopyVirtIO.IsChecked $mountDir = $sync.MicrowinMountDir.Text @@ -90,8 +85,11 @@ public class PowerManagement { } } - $imgVersion = (Get-WindowsImage -ImagePath $mountDir\sources\install.wim -Index $index).Version + $imgVersion = (Get-WindowsImage -ImagePath "$mountDir\sources\install.wim" -Index $index).Version + # Windows Setup is the second index in the boot image. + $bootVersion = (Get-WindowsImage -ImagePath "$mountDir\sources\boot.wim" -Index 2).Version Write-Host "The Windows Image Build Version is: $imgVersion" + Write-Host "The WinPE boot image Build Version is: $bootVersion" # Detect image version to avoid performing MicroWin processing on Windows 8 and earlier if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,10240,0))) -eq $false) { @@ -175,33 +173,31 @@ public class PowerManagement { } } - if ($WPBT) { - Write-Host "Disabling WPBT Execution" - reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM" - reg add "HKLM\zSYSTEM\ControlSet001\Control\Session Manager" /v DisableWpbtExecution /t REG_DWORD /d 1 /f - reg unload HKLM\zSYSTEM - } + Write-Host "Disabling WPBT Execution" + reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM" + reg add "HKLM\zSYSTEM\ControlSet001\Control\Session Manager" /v DisableWpbtExecution /t REG_DWORD /d 1 /f + reg unload HKLM\zSYSTEM - if ($skipFla) { - Write-Host "Skipping first logon animation..." - reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" - reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /f - reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /ve /t REG_SZ /d "Stop First Logon Animation Process" /f - reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /v StubPath /t REG_EXPAND_SZ /d '""%WINDIR%\System32\cmd.exe"" /C ""taskkill /f /im firstlogonanim.exe""' /f - reg unload HKLM\zSOFTWARE - } + Write-Host "Skipping first logon animation..." + reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" + reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /f + reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /f /ve /t REG_SZ /d "Stop First Logon Animation Process" + reg add "HKLM\zSOFTWARE\Microsoft\Active Setup\Installed Components\CMP_NoFla" /f /v StubPath /t REG_EXPAND_SZ /d '\"%WINDIR%\System32\cmd.exe\" /C \"taskkill /f /im firstlogonanim.exe\"' + reg unload HKLM\zSOFTWARE - if ($unsupported) { - Write-Host "Bypassing system requirements (locally)" - reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f - reg add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f - reg add "HKLM\SYSTEM\Setup\LabConfig" /v "BypassCPUCheck" /t REG_DWORD /d 1 /f - reg add "HKLM\SYSTEM\Setup\LabConfig" /v "BypassRAMCheck" /t REG_DWORD /d 1 /f - reg add "HKLM\SYSTEM\Setup\LabConfig" /v "BypassSecureBootCheck" /t REG_DWORD /d 1 /f - reg add "HKLM\SYSTEM\Setup\LabConfig" /v "BypassStorageCheck" /t REG_DWORD /d 1 /f - reg add "HKLM\SYSTEM\Setup\LabConfig" /v "BypassTPMCheck" /t REG_DWORD /d 1 /f - reg add "HKLM\SYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f - } + # We have to prepare the target system to accept the diagnostics script + reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" + reg add "HKLM\zSOFTWARE\WinUtil" /f + reg add "HKLM\zSOFTWARE\WinUtil" /f /v "ToolboxVersion" /t REG_SZ /d "$($sync.version)" + reg add "HKLM\zSOFTWARE\WinUtil" /f /v "MicroWinBuildDate" /t REG_SZ /d "$((Get-Date).ToString('yyMMdd-HHmm'))" + + # REAL software developers set execution policies to unrestricted but, because we're targeting + # mainstream population, we have to lower the level of "riskiness" -- set remotesigned; at least that + # lets us run PWSH scripts that WE create. Execution policies don't really make sense anyway if common sense + # is lacking. + reg add "HKLM\zSOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v "ExecutionPolicy" /t REG_SZ /d "RemoteSigned" /f + + reg unload HKLM\zSOFTWARE if ($importVirtIO) { Write-Host "Copying VirtIO drivers..." @@ -217,7 +213,10 @@ public class PowerManagement { Microwin-RemoveProvisionedPackages -UseCmdlets $true # Detect Windows 11 24H2 and add dependency to FileExp to prevent Explorer look from going back - thanks @WitherOrNot and @thecatontheceiling - if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,1))) -eq $true) { + # ----- UPDATE UPDATE UPDATE: they fixed this in 10.0.26100.7019. DO NOT DO THIS OTHERWISE IT BREAKS EXPLORER AGAIN BECAUSE THE CHEEKY LITTLE + # ----- PoS CHANGED APPRUNTIME.CBS TO APPRUNTIME.CBS.1.6. Thing is, we don't need to patch this in those builds because it no longer breaks + # ----- when you don't patch. + if (((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,1))) -eq $true) -and ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,7019))) -eq $false)) { try { if (Test-Path "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml" -PathType Leaf) { # Found the culprit. Do the following: @@ -302,11 +301,6 @@ public class PowerManagement { Copy-Item "$env:temp\FirstStartup.ps1" "$($scratchDir)\Windows\FirstStartup.ps1" -force Write-Host "Done copy FirstRun.ps1" - Write-Host "Copy link to winutil.ps1 into the ISO" - $desktopDir = "$($scratchDir)\Windows\Users\Default\Desktop" - New-Item -ItemType Directory -Force -Path "$desktopDir" - dism /English /image:$($scratchDir) /set-profilepath:"$($scratchDir)\Windows\Users\Default" - Write-Host "Copy checkinstall.cmd into the ISO" Microwin-NewCheckInstall Copy-Item "$env:temp\checkinstall.cmd" "$($scratchDir)\Windows\checkinstall.cmd" -force @@ -316,7 +310,6 @@ public class PowerManagement { New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\System32\OOBE\BYPASSNRO" Write-Host "Loading registry" - reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS" reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default" reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat" reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" @@ -375,9 +368,8 @@ public class PowerManagement { Write-Host "Disabling Reserved Storage" reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager" /v "ShippedWithReserves" /t REG_DWORD /d 0 /f - Write-Host "Changing theme to dark. This only works on Activated Windows" - reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "AppsUseLightTheme" /t REG_DWORD /d 0 /f - reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "SystemUsesLightTheme" /t REG_DWORD /d 0 /f + Write-Host "Showing file extensions..." + reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,21996,1))) -eq $false) { # We're dealing with Windows 10. Configure sane desktop settings. NOTE: even though stuff to disable News and Interests is there, @@ -397,7 +389,6 @@ public class PowerManagement { Write-Error "An unexpected error occurred: $_" } finally { Write-Host "Unmounting Registry..." - reg unload HKLM\zCOMPONENTS reg unload HKLM\zDEFAULT reg unload HKLM\zNTUSER reg unload HKLM\zSOFTWARE @@ -406,9 +397,45 @@ public class PowerManagement { Write-Host "Cleaning up image..." dism /English /image:$scratchDir /Cleanup-Image /StartComponentCleanup /ResetBase Write-Host "Cleanup complete." + $committed = $false + $unmounted = $false + + Write-Host "Saving image..." + + try { + Save-WindowsImage -Path "$scratchDir" + $committed = $true + } catch { + do { + # we'll prevent stuff inside this loop from throwing exceptions and breaking from the loop. + try { + Save-WindowsImage -Path "$scratchDir" + $committed = $true + } catch { + Write-Host "Commit operation unsuccessful. Trying again after 3 seconds..." + Start-Sleep -Seconds 3 + } + } until ($committed) + } Write-Host "Unmounting image..." - Dismount-WindowsImage -Path "$scratchDir" -Save + + try { + # because we've already saved the changes earlier, we can safely discard + Dismount-WindowsImage -Discard -Path "$scratchDir" + $unmounted = $true + } catch { + do { + # we'll prevent stuff inside this loop from throwing exceptions and breaking from the loop. + try { + Dismount-WindowsImage -Discard -Path "$scratchDir" + $unmounted = $true + } catch { + Write-Host "Unmount operation unsuccessful. Trying again after 3 seconds..." + Start-Sleep -Seconds 3 + } + } until ($unmounted) + } } try { @@ -433,20 +460,6 @@ public class PowerManagement { } Write-Host "Windows image completed. Continuing with boot.wim." - $esd = $sync.MicroWinESD.IsChecked - if ($esd) { - Write-Host "Converting install image to ESD." - try { - Export-WindowsImage -SourceImagePath "$mountDir\sources\install.wim" -SourceIndex $index -DestinationImagePath "$mountDir\sources\install.esd" -CompressionType "Recovery" - Remove-Item "$mountDir\sources\install.wim" - Write-Host "Converted install image to ESD." - } catch { - Start-Process -FilePath "$env:SystemRoot\System32\dism.exe" -ArgumentList "/export-image /sourceimagefile:`"$mountDir\sources\install.wim`" /sourceindex:1 /destinationimagefile:`"$mountDir\sources\install.esd`" /compress:recovery" -Wait -NoNewWindow - Remove-Item "$mountDir\sources\install.wim" - Write-Host "Converted install image to ESD." - } - } - # Next step boot image Write-Host "Mounting boot image $mountDir\sources\boot.wim into $scratchDir" Mount-WindowsImage -ImagePath "$mountDir\sources\boot.wim" -Index 2 -Path "$scratchDir" @@ -462,7 +475,6 @@ public class PowerManagement { } Write-Host "Loading registry..." - reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS" >$null reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default" >$null reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat" >$null reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" >$null @@ -480,27 +492,86 @@ public class PowerManagement { reg add "HKLM\zSYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f # Fix Computer Restarted Unexpectedly Error on New Bare Metal Install reg add "HKLM\zSYSTEM\Setup\Status\ChildCompletion" /v "setup.exe" /t REG_DWORD /d 3 /f + + # Force old Setup on 24H2+ WinPE images due to personal preference; it's simply faster and + # more reliable than MoSetup. I simply can't stand that new setup system. + if ((Microwin-TestCompatibleImage $bootVersion $([System.Version]::new(10,0,26040,0))) -and (Test-Path -Path "$scratchDir\sources\setup.exe" -PathType Leaf)) { + reg add "HKLM\zSYSTEM\Setup" /f /v "CmdLine" /t REG_SZ /d "\sources\setup.exe" + } } catch { Write-Error "An unexpected error occurred: $_" } finally { Write-Host "Unmounting Registry..." - reg unload HKLM\zCOMPONENTS reg unload HKLM\zDEFAULT reg unload HKLM\zNTUSER reg unload HKLM\zSOFTWARE reg unload HKLM\zSYSTEM + $committed = $false + $unmounted = $false + + Write-Host "Saving image..." + + try { + Save-WindowsImage -Path "$scratchDir" + $committed = $true + } catch { + do { + # we'll prevent stuff inside this loop from throwing exceptions and breaking from the loop. + try { + Save-WindowsImage -Path "$scratchDir" + $committed = $true + } catch { + Write-Host "Commit operation unsuccessful. Trying again after 3 seconds..." + Start-Sleep -Seconds 3 + } + } until ($committed) + } + Write-Host "Unmounting image..." - Dismount-WindowsImage -Path "$scratchDir" -Save + + try { + # because we've already saved the changes earlier, we can safely discard + Dismount-WindowsImage -Discard -Path "$scratchDir" + $unmounted = $true + } catch { + do { + # we'll prevent stuff inside this loop from throwing exceptions and breaking from the loop. + try { + Dismount-WindowsImage -Discard -Path "$scratchDir" + $unmounted = $true + } catch { + Write-Host "Unmount operation unsuccessful. Trying again after 3 seconds..." + Start-Sleep -Seconds 3 + } + } until ($unmounted) + } Write-Host "Creating ISO image" + $peToolsPath = "" + + $adkKitsRoot = Microwin-GetKitsRoot -wow64environment $false + $adkKitsRoot_WOW64Environ = Microwin-GetKitsRoot -wow64environment $true + + $expectedADKPath = "$($adkKitsRoot)Assessment and Deployment Kit" + $expectedADKPath_WOW64Environ = "$($adkKitsRoot_WOW64Environ)Assessment and Deployment Kit" + # if we downloaded oscdimg from github it will be in the temp directory so use it # if it is not in temp it is part of ADK and is in global PATH so just set it to oscdimg.exe $oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe' - $oscdImgFound = Test-Path $oscdimgPath -PathType Leaf - if (!$oscdImgFound) { - $oscdimgPath = "oscdimg.exe" + $oscdImgFound = Test-Path -Path "$oscdimgPath" -PathType Leaf + if ((-not ($oscdImgFound)) -and ((Microwin-TestKitsRootPaths -adkKitsRootPath "$expectedADKPath" -adkKitsRootPath_WOW64Environ "$expectedADKPath_WOW64Environ") -eq $true)) { + if ($expectedADKPath -ne "Assessment and Deployment Kit") { $peToolsPath = $expectedADKPath } + if (($peToolsPath -eq "") -and ($expectedADKPath_WOW64Environ -ne "Assessment and Deployment Kit")) { $peToolsPath = $expectedADKPath_WOW64Environ } + + Write-Host "Using $peToolsPath as the Preinstallation Environment tools path..." + # Paths change depending on platform + if ([Environment]::Is64BitOperatingSystem) { + $oscdimgPath = "$peToolsPath\Deployment Tools\amd64\Oscdimg\oscdimg.exe" + } else { + $oscdimgPath = "$peToolsPath\Deployment Tools\x86\Oscdimg\oscdimg.exe" + } } Write-Host "[INFO] Using oscdimg.exe from: $oscdimgPath" @@ -511,12 +582,6 @@ public class PowerManagement { Write-Host "OSCDIMG Error Level : $($oscdimgProc.ExitCode)" - if ($copyToUSB) { - Write-Host "Copying target ISO to the USB drive" - Microwin-CopyToUSB("$($SaveDialog.FileName)") - if ($?) { Write-Host "Done Copying target ISO to USB drive!" } else { Write-Host "ISO copy failed." } - } - Write-Host " _____ " Write-Host "(____ \ " Write-Host " _ \ \ ___ ____ ____ " diff --git a/functions/microwin/Invoke-MicrowinGetIso.ps1 b/functions/microwin/Invoke-MicrowinGetIso.ps1 index c8fe8ae2..e32c1033 100644 --- a/functions/microwin/Invoke-MicrowinGetIso.ps1 +++ b/functions/microwin/Invoke-MicrowinGetIso.ps1 @@ -122,46 +122,60 @@ function Invoke-MicrowinGetIso { Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo" Invoke-MicrowinBusyInfo -action "wip" -message "Checking system requirements..." -interactive $false + $adkKitsRoot = Microwin-GetKitsRoot -wow64environment $false + $adkKitsRoot_WOW64Environ = Microwin-GetKitsRoot -wow64environment $true + + $expectedADKPath = "$($adkKitsRoot)Assessment and Deployment Kit" + $expectedADKPath_WOW64Environ = "$($adkKitsRoot_WOW64Environ)Assessment and Deployment Kit" + $oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe' - $oscdImgFound = [bool] (Get-Command -ErrorAction Ignore -Type Application oscdimg.exe) -or (Test-Path $oscdimgPath -PathType Leaf) + $oscdImgFound = [bool] (Microwin-TestKitsRootPaths -adkKitsRootPath "$expectedADKPath" -adkKitsRootPath_WOW64Environ "$expectedADKPath_WOW64Environ") -or (Test-Path $oscdimgPath -PathType Leaf) Write-Host "oscdimg.exe on system: $oscdImgFound" - if (!$oscdImgFound) { - $downloadFromGitHub = $sync.WPFMicrowinDownloadFromGitHub.IsChecked - - if (!$downloadFromGitHub) { - # only show the message to people who did check the box to download from github, if you check the box - # you consent to downloading it, no need to show extra dialogs - [System.Windows.MessageBox]::Show("oscdimg.exe is not found on the system, winutil will now attempt do download and install it using choco. This might take a long time.") - # the step below needs choco to download oscdimg - # Install Choco if not already present - Install-WinUtilChoco - $chocoFound = [bool] (Get-Command -ErrorAction Ignore -Type Application choco) - Write-Host "choco on system: $chocoFound" - if (!$chocoFound) { - [System.Windows.MessageBox]::Show("choco.exe is not found on the system, you need choco to download oscdimg.exe") - return - } - - Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install windows-adk-oscdimg" - $msg = "oscdimg is installed, now close, reopen PowerShell terminal and re-launch winutil.ps1" - Invoke-MicrowinBusyInfo -action "done" -message $msg # We set it to done because it immediately returns from this function - [System.Windows.MessageBox]::Show($msg) - return + if (-not ($oscdImgFound)) { + # First we try to grab it from github, if not, run the ADK installer. + if ((Microwin-GetOscdimg -oscdimgPath $oscdimgPath) -eq $true) { + Write-Host "OSCDIMG download succeeded." } else { - [System.Windows.MessageBox]::Show("oscdimg.exe is not found on the system, winutil will now attempt do download and install it from github. This might take a long time.") - Invoke-MicrowinBusyInfo -action "wip" -message "Downloading oscdimg.exe..." -interactive $false - Microwin-GetOscdimg -oscdimgPath $oscdimgPath - $oscdImgFound = Test-Path $oscdimgPath -PathType Leaf - if (!$oscdImgFound) { - $msg = "oscdimg was not downloaded can not proceed" - Invoke-MicrowinBusyInfo -action "warning" -message $msg - [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) + Write-Host "OSCDIMG could not be downloaded from GitHub. Downloading deployment tools..." + if (-not (Microwin-GetAdkDeploymentTools)) { + Invoke-MicrowinBusyInfo -action "warning" -message "Neither OSCDIMG nor ADK could be downloaded." + Write-Host "Neither OSCDIMG nor ADK could be downloaded." return } else { - Write-Host "oscdimg.exe was successfully downloaded from github" + $msg = "ADK/OSCDIMG is installed, now restart this process." + Invoke-MicrowinBusyInfo -action "done" -message $msg # We set it to done because it immediately returns from this function + [System.Windows.MessageBox]::Show($msg) + Remove-Item -Path "$env:TEMP\adksetup.exe" -Force -ErrorAction SilentlyContinue + return } } + } elseif (Microwin-TestKitsRootPaths -adkKitsRootPath "$expectedADKPath" -adkKitsRootPath_WOW64Environ "$expectedADKPath_WOW64Environ") { + # We have to guess where oscdimg is. We'll check both values... + $peToolsPath = "" + + if ($expectedADKPath -ne "Assessment and Deployment Kit") { $peToolsPath = $expectedADKPath } + if (($peToolsPath -eq "") -and ($expectedADKPath_WOW64Environ -ne "Assessment and Deployment Kit")) { $peToolsPath = $expectedADKPath_WOW64Environ } + + Write-Host "Using $peToolsPath as the Preinstallation Environment tools path..." + # Paths change depending on platform + if ([Environment]::Is64BitOperatingSystem) { + $oscdimgPath = "$peToolsPath\Deployment Tools\amd64\Oscdimg\oscdimg.exe" + } else { + $oscdimgPath = "$peToolsPath\Deployment Tools\x86\Oscdimg\oscdimg.exe" + } + + # If it's a non-existent file, we won't continue. + if (-not (Test-Path -Path "$oscdimgPath" -PathType Leaf)) { + $oscdimgFound = $false + } + } + + $oscdImgFound = [bool] (Microwin-TestKitsRootPaths -adkKitsRootPath "$expectedADKPath" -adkKitsRootPath_WOW64Environ "$expectedADKPath_WOW64Environ") -or (Test-Path $oscdimgPath -PathType Leaf) + + if (-not ($oscdimgFound)) { + [System.Windows.MessageBox]::Show("oscdimg.exe is not found on the system. Cannot continue.") + return } Invoke-MicrowinBusyInfo -action "wip" -message "Checking disk space..." -interactive $false @@ -209,23 +223,6 @@ function Invoke-MicrowinGetIso { # there is probably a better way of doing this, I don't have time to figure this out $sync.MicrowinIsoDrive.Text = $driveLetter - $mountedISOPath = (Split-Path -Path "$filePath") - if ($sync.MicrowinScratchDirBox.Text.Trim() -eq "Scratch") { - $sync.MicrowinScratchDirBox.Text ="" - } - - $UseISOScratchDir = $sync.WPFMicrowinISOScratchDir.IsChecked - - if ($UseISOScratchDir) { - $sync.MicrowinScratchDirBox.Text=$mountedISOPath - } - - if( -Not $sync.MicrowinScratchDirBox.Text.EndsWith('\') -And $sync.MicrowinScratchDirBox.Text.Length -gt 1) { - - $sync.MicrowinScratchDirBox.Text = Join-Path $sync.MicrowinScratchDirBox.Text.Trim() '\' - - } - # Detect if the folders already exist and remove them if (($sync.MicrowinMountDir.Text -ne "") -and (Test-Path -Path $sync.MicrowinMountDir.Text)) { try { @@ -244,13 +241,8 @@ function Invoke-MicrowinGetIso { $randomMicrowinScratch = "MicrowinScratch_${timestamp}_${randomNumber}" $sync.BusyText.Text=" - Mounting" Write-Host "Mounting Iso. Please wait." - if ($sync.MicrowinScratchDirBox.Text -eq "") { - $mountDir = Join-Path $env:TEMP $randomMicrowin - $scratchDir = Join-Path $env:TEMP $randomMicrowinScratch - } else { - $scratchDir = $sync.MicrowinScratchDirBox.Text+"Scratch" - $mountDir = $sync.MicrowinScratchDirBox.Text+"micro" - } + $mountDir = Join-Path $env:TEMP $randomMicrowin + $scratchDir = Join-Path $env:TEMP $randomMicrowinScratch $sync.MicrowinMountDir.Text = $mountDir $sync.MicrowinScratchDir.Text = $scratchDir diff --git a/functions/microwin/Microwin-CopyToUSB.ps1 b/functions/microwin/Microwin-CopyToUSB.ps1 deleted file mode 100644 index f1b37c95..00000000 --- a/functions/microwin/Microwin-CopyToUSB.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -function Microwin-CopyToUSB([string]$fileToCopy) { - foreach ($volume in Get-Volume) { - if ($volume -and $volume.FileSystemLabel -ieq "ventoy") { - $destinationPath = "$($volume.DriveLetter):\" - #Copy-Item -Path $fileToCopy -Destination $destinationPath -Force - # Get the total size of the file - $totalSize = (Get-Item "$fileToCopy").length - - Copy-Item -Path "$fileToCopy" -Destination "$destinationPath" -Verbose -Force -Recurse -Container -PassThru | - ForEach-Object { - # Calculate the percentage completed - $completed = ($_.BytesTransferred / $totalSize) * 100 - - # Display the progress bar - Write-Progress -Activity "Copying File" -Status "Progress" -PercentComplete $completed -CurrentOperation ("{0:N2} MB / {1:N2} MB" -f ($_.BytesTransferred / 1MB), ($totalSize / 1MB)) - } - - Write-Host "File copied to Ventoy drive $($volume.DriveLetter)" - - # Detect if config files are present, move them if they are, and configure the Ventoy drive to not bypass the requirements - $customVentoyConfig = @' -{ - "control":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ], - "control_legacy":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ], - "control_uefi":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ], - "control_ia32":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ], - "control_aa64":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ], - "control_mips":[ - { "VTOY_WIN11_BYPASS_CHECK": "0" }, - { "VTOY_WIN11_BYPASS_NRO": "0" } - ] -} -'@ - - try { - Write-Host "Writing custom Ventoy configuration. Please wait..." - if (Test-Path -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -PathType Leaf) { - Write-Host "A Ventoy configuration file exists. Moving it..." - Move-Item -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -Destination "$($volume.DriveLetter):\ventoy\ventoy.json.old" -Force - Write-Host "Existing Ventoy configuration has been moved to `"ventoy.json.old`". Feel free to put your config back into the `"ventoy.json`" file." - } - if (-not (Test-Path -Path "$($volume.DriveLetter):\ventoy")) { - New-Item -Path "$($volume.DriveLetter):\ventoy" -ItemType Directory -Force | Out-Null - } - $customVentoyConfig | Out-File -FilePath "$($volume.DriveLetter):\ventoy\ventoy.json" -Encoding utf8 -Force - Write-Host "The Ventoy drive has been successfully configured." - } catch { - Write-Host "Could not configure Ventoy drive. Error: $($_.Exception.Message)`n" - Write-Host "Be sure to add the following configuration to the Ventoy drive by either creating a `"ventoy.json`" file in the `"ventoy`" directory (create it if it doesn't exist) or by editing an existing one: `n`n$customVentoyConfig`n" - Write-Host "Failure to do this will cause conflicts with your target ISO file." - } - return - } - } - Write-Host "Ventoy USB Key is not inserted" -} diff --git a/functions/microwin/Microwin-GetAdkDeploymentTools.ps1 b/functions/microwin/Microwin-GetAdkDeploymentTools.ps1 new file mode 100644 index 00000000..20df1faa --- /dev/null +++ b/functions/microwin/Microwin-GetAdkDeploymentTools.ps1 @@ -0,0 +1,25 @@ +function Microwin-GetAdkDeploymentTools { + <# + .DESCRIPTION + This function will download the deployment tools from Microsoft + + .EXAMPLE + Microwin-GetAdkDeploymentTools + #> + + # ADK 10.1.28000.1 download link is the same; no need to guess it + $adkDownloadLink = "https://download.microsoft.com/download/615540bc-be0b-433a-b91b-1f2b0642bb24/adk/adksetup.exe" + $adkVersion = "10.1.28000.1" + Write-Host "Downloading ADK version $adkVersion ..." + Invoke-WebRequest -UseBasicParsing -Uri "$adkDownloadLink" -OutFile "$env:TEMP\adksetup.exe" + + if ((-not ($?)) -or (-not (Test-Path -Path "$env:TEMP\adksetup.exe" -PathType Leaf))) { + Write-Host "ADK could not be downloaded." + return $false + } + + Write-Host "Installing ADK version $adkVersion -- This may take a few minutes..." + Start-Process -FilePath "$env:TEMP\adksetup.exe" -ArgumentList "/features OptionId.DeploymentTools /q /ceip off" -Wait + + return $? +} diff --git a/functions/microwin/Microwin-GetKitsRoot.ps1 b/functions/microwin/Microwin-GetKitsRoot.ps1 new file mode 100644 index 00000000..594f5f6a --- /dev/null +++ b/functions/microwin/Microwin-GetKitsRoot.ps1 @@ -0,0 +1,40 @@ +function Microwin-GetKitsRoot { + <# + .SYNOPSIS + Gets the kits root path for the Windows Assessment and Deployment Kit (ADK) + .PARAMETER wow64environment + Determines whether to search in a WOW64 compatibility environment (HKLM\SOFTWARE\WOW6432Node) + .OUTPUTS + The path to the kits root + #> + + param ( + [Parameter(Mandatory = $true, Position = 0)] [bool]$wow64environment + ) + + $adk10KitsRoot = "" + + # if we set the wow64 bit on and we're on a 32-bit system, then we prematurely return the value + if (($wow64environment -eq $true) -and (-not [Environment]::Is64BitOperatingSystem)) { + return $adk10KitsRoot + } + + $regPath = "" + if ($wow64environment) { + $regPath = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots" + } else { + $regPath = "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" + } + + if ((Test-Path "$regPath") -eq $false) { + return $adk10KitsRoot + } + + try { + $adk10KitsRoot = Get-ItemPropertyValue -Path $regPath -Name "KitsRoot10" -ErrorAction Stop + } catch { + Write-Debug "Could not find ADK." + } + + return $adk10KitsRoot +} diff --git a/functions/microwin/Microwin-GetOscdimg.ps1 b/functions/microwin/Microwin-GetOscdimg.ps1 index f395f71f..643a56e5 100644 --- a/functions/microwin/Microwin-GetOscdimg.ps1 +++ b/functions/microwin/Microwin-GetOscdimg.ps1 @@ -15,6 +15,10 @@ function Microwin-GetOscdimg { $oscdimgPath = "$env:TEMP\oscdimg.exe" $downloadUrl = "https://github.com/ChrisTitusTech/winutil/raw/main/releases/oscdimg.exe" Invoke-RestMethod -Uri $downloadUrl -OutFile $oscdimgPath + if (-not (Test-Path "$oscdimgPath" -PathType Leaf)) { + Write-Host "OSCDIMG could not be downloaded." + return $false + } $hashResult = Get-FileHash -Path $oscdimgPath -Algorithm SHA256 $sha256Hash = $hashResult.Hash @@ -23,7 +27,9 @@ function Microwin-GetOscdimg { $expectedHash = "AB9E161049D293B544961BFDF2D61244ADE79376D6423DF4F60BF9B147D3C78D" # Replace with the actual expected hash if ($sha256Hash -eq $expectedHash) { Write-Host "Hashes match. File is verified." + return $true } else { Write-Host "Hashes do not match. File may be corrupted or tampered with." + return $false } } diff --git a/functions/microwin/Microwin-NewFirstRun.ps1 b/functions/microwin/Microwin-NewFirstRun.ps1 index 0fe6ff1d..2cbf842d 100644 --- a/functions/microwin/Microwin-NewFirstRun.ps1 +++ b/functions/microwin/Microwin-NewFirstRun.ps1 @@ -103,6 +103,35 @@ function Microwin-NewFirstRun { reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Start" /v ShowRecentList /t REG_DWORD /d 0 /f reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v Start_TrackDocs /t REG_DWORD /d 0 /f + # Color Modes -- requires sending messages to apply to everything + reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "AppsUseLightTheme" /t REG_DWORD /d 0 /f + reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "SystemUsesLightTheme" /t REG_DWORD /d 0 /f + + # Send the WM_SETTINGCHANGE message to all windows + Add-Type -TypeDefinition @" +using System; +using System.Runtime.InteropServices; +public class Win32 { + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] + public static extern IntPtr SendMessageTimeout( + IntPtr hWnd, + uint Msg, + IntPtr wParam, + string lParam, + uint fuFlags, + uint uTimeout, + out IntPtr lpdwResult); +} +"@ + + $HWND_BROADCAST = [IntPtr]0xffff + $WM_SETTINGCHANGE = 0x1A + $SMTO_ABORTIFHUNG = 0x2 + $timeout = 100 + + # Send the broadcast message to all windows + [Win32]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [IntPtr]::Zero, "ImmersiveColorSet", $SMTO_ABORTIFHUNG, $timeout, [ref]([IntPtr]::Zero)) + Clear-Host Write-Host "The taskbar will take around a minute to show up, but you can start using your computer now. Try pressing the Windows key to open the Start menu, or Windows + E to launch File Explorer." Start-Sleep -Seconds 10 diff --git a/functions/microwin/Microwin-TestKitsRootPaths.ps1 b/functions/microwin/Microwin-TestKitsRootPaths.ps1 new file mode 100644 index 00000000..2188c16d --- /dev/null +++ b/functions/microwin/Microwin-TestKitsRootPaths.ps1 @@ -0,0 +1,11 @@ +function Microwin-TestKitsRootPaths { + param ( + [Parameter(Mandatory = $true, Position = 0)] [string]$adkKitsRootPath, + [Parameter(Mandatory = $true, Position = 1)] [string]$adkKitsRootPath_WOW64Environ + ) + + if (Test-Path "$adkKitsRootPath") { return $true } + if (Test-Path "$adkKitsRootPath_WOW64Environ") { return $true } + + return $false +} diff --git a/functions/public/Invoke-ScratchDialog.ps1 b/functions/public/Invoke-ScratchDialog.ps1 deleted file mode 100644 index a35366c6..00000000 --- a/functions/public/Invoke-ScratchDialog.ps1 +++ /dev/null @@ -1,28 +0,0 @@ - -function Invoke-ScratchDialog { - - <# - - .SYNOPSIS - Enable Editable Text box Alternate Scratch path - - .PARAMETER Button - #> - $sync.WPFMicrowinISOScratchDir.IsChecked - - - [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null - $Dialog = New-Object System.Windows.Forms.FolderBrowserDialog - $Dialog.SelectedPath = $sync.MicrowinScratchDirBox.Text - $Dialog.ShowDialog() - $filePath = $Dialog.SelectedPath - Write-Host "No ISO is chosen+ $filePath" - - if ([string]::IsNullOrEmpty($filePath)) { - Write-Host "No Folder had chosen" - return - } - - $sync.MicrowinScratchDirBox.Text = Join-Path $filePath "\" - -} diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index 8f8ace51..68f91e2e 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -59,7 +59,6 @@ function Invoke-WPFButton { "WPFGetIso" {Invoke-MicrowinGetIso} "WPFMicrowin" {Invoke-Microwin} "WPFCloseButton" {Invoke-WPFCloseButton} - "MicrowinScratchDirBT" {Invoke-ScratchDialog} "WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile} "WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile} "WPFWinUtilSSHServer" {Invoke-WPFSSHServer} diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 295df951..45c5a805 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -1350,41 +1350,11 @@ HorizontalAlignment="Stretch"> - Choose a Windows ISO file that you've downloaded Check the status in the console - Scratch directory settings (optional) - - - - - - - - - - - - - Custom user settings (leave empty for default user) User name (20 characters max.): - Tweaks (leave empty for default settings) - - - - WinUtil configuration file (JSON) @@ -1564,6 +1527,7 @@ MicroWin features: - Remove Telemetry and Tracking - Fast Install using either the "User" local account or the account of your choosing + - Bypasses Windows 11 System Requirements on unsupported computers - No internet requirement for install - Apps debloat