diff --git a/README.md b/README.md index f39750b..40c33a2 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ You can now use it on ANY Windows 11 release (not just a specific build), as wel This is made possible thanks to the much-improved scripting capabilities of PowerShell, compared to the older Batch release.
Since it is written in PowerShell, you need to set the execution policy to `Unrestricted`, so that you could run the script. -If you haven't done this before, make sure to run `Set-ExecutionPolicy unrestricted` as administrator in PowerShell before running the script, otherwise it would just crash. +If you haven't done this before, make sure to run `Set-ExecutionPolicy -Scope Process unrestricted` as administrator in PowerShell before running the script, otherwise it would just crash. This is a script created to automate the build of a streamlined Windows 11 image, similar to tiny11. diff --git a/Run.bat b/Run.bat new file mode 100644 index 0000000..996c80a --- /dev/null +++ b/Run.bat @@ -0,0 +1,5 @@ +:: Reference from https://github.com/Raphire/Win11Debloat/blob/master/Run.bat licensed under MIT license. + +@echo off + +Powershell -ExecutionPolicy Bypass -Command "& {Start-Process Powershell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dp0tiny11maker.ps1""' -Verb RunAs}" diff --git a/tiny11Coremaker.ps1 b/tiny11Coremaker.ps1 index 18b9490..f2934d1 100644 --- a/tiny11Coremaker.ps1 +++ b/tiny11Coremaker.ps1 @@ -1,12 +1,14 @@ # Enable debugging Set-PSDebug -Trace 1 -# Check if PowerShell execution is restricted -if ((Get-ExecutionPolicy) -eq 'Restricted') { - Write-Host "Your current PowerShell Execution Policy is set to Restricted, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)" +# Check if PowerShell execution is Restricted or AllSigned or Undefined +$needchange = @("AllSigned", "Restricted", "Undefined") +$curpolicy = Get-ExecutionPolicy +if ($curpolicy -in $needchange) { + Write-Host "Your current PowerShell Execution Policy is set to $curpolicy, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)" $response = Read-Host if ($response -eq 'yes') { - Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm:$false + Set-ExecutionPolicy RemoteSigned -Scope Process -Confirm:$false } else { Write-Host "The script cannot be run without changing the execution policy. Exiting..." exit @@ -730,16 +732,25 @@ Write-Host "Exporting ESD. This may take a while..." Remove-Item "$mainOSDrive\tiny11\sources\install.wim" > $null 2>&1 Write-Host "The tiny11 image is now completed. Proceeding with the making of the ISO..." Write-Host "Creating ISO image..." -$ADKDepTools = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture\Oscdimg" +# 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 ([System.IO.Directory]::Exists($ADKDepTools)) { +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 "ADK folder not found. Will be using bundled oscdimg.exe." - - + 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 (-not (Test-Path -Path $localOSCDIMGPath)) { diff --git a/tiny11maker.ps1 b/tiny11maker.ps1 index 03dfedd..614ae01 100644 --- a/tiny11maker.ps1 +++ b/tiny11maker.ps1 @@ -14,12 +14,14 @@ if (-not $ScratchDisk) { Write-Output "Scratch disk set to $ScratchDisk" -# Check if PowerShell execution is restricted -if ((Get-ExecutionPolicy) -eq 'Restricted') { - Write-Host "Your current PowerShell Execution Policy is set to Restricted, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)" +# Check if PowerShell execution is Restricted or AllSigned or Undefined +$needchange = @("AllSigned", "Restricted", "Undefined") +$curpolicy = Get-ExecutionPolicy +if ($curpolicy -in $needchange) { + Write-Host "Your current PowerShell Execution Policy is set to $curpolicy, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)" $response = Read-Host if ($response -eq 'yes') { - Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm:$false + Set-ExecutionPolicy RemoteSigned -Scope Process -Confirm:$false } else { Write-Host "The script cannot be run without changing the execution policy. Exiting..." exit @@ -98,8 +100,9 @@ try { # This block will catch the error and suppress it. } New-Item -ItemType Directory -Force -Path "$ScratchDisk\scratchdir" > $null -Mount-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim -Index $index -Path $ScratchDisk\scratchdir +Mount-WindowsImage -ImagePath $wimFilePath -Index $index -Path $ScratchDisk\scratchdir +# Powershell dism module does not have direct equivalent for /Get-Intl $imageIntl = & dism /English /Get-Intl "/Image:$($ScratchDisk)\scratchdir" $languageLine = $imageIntl -split '\n' | Where-Object { $_ -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' } @@ -110,33 +113,29 @@ if ($languageLine) { Write-Host "Default system UI language code not found." } -$imageInfo = & 'dism' '/English' '/Get-WimInfo' "/wimFile:$($ScratchDisk)\tiny11\sources\install.wim" "/index:$index" -$lines = $imageInfo -split '\r?\n' - -foreach ($line in $lines) { - if ($line -like '*Architecture : *') { - $architecture = $line -replace 'Architecture : ','' - # If the architecture is x64, replace it with amd64 - if ($architecture -eq 'x64') { - $architecture = 'amd64' - } - Write-Host "Architecture: $architecture" - break - } +# Defined in (Microsoft.Dism.Commands.ImageInfoObject).Architecture formatting script +# 0 -> x86, 5 -> arm(currently unused), 6 -> ia64(currently unused), 9 -> x64, 12 -> arm64 +switch ((Get-WindowsImage -ImagePath $wimFilePath -Index $index).Architecture) +{ + 0 { $architecture = "x86" } + 9 { $architecture = "amd64" } + 12 { $architecture = "arm64" } } -if (-not $architecture) { +if (Test-Path variable:architecture) { + Write-Host "Architecture: $architecture" +} else { Write-Host "Architecture information not found." } -Write-Host "Mounting complete! Performing removal of applications..." -$packages = & 'dism' '/English' "/image:$($ScratchDisk)\scratchdir" '/Get-ProvisionedAppxPackages' | +Write-Host "Mounting complete! Performing removal of applications...`n" + +$packages = Get-ProvisionedAppxPackage -Path "$ScratchDisk\scratchdir" | ForEach-Object { - if ($_ -match 'PackageName : (.*)') { - $matches[1] - } + $_.PackageName } + $packagePrefixes = 'Clipchamp.Clipchamp_', 'Microsoft.BingNews_', 'Microsoft.BingWeather_', 'Microsoft.GamingApp_', 'Microsoft.GetHelp_', 'Microsoft.Getstarted_', 'Microsoft.MicrosoftOfficeHub_', 'Microsoft.MicrosoftSolitaireCollection_', 'Microsoft.People_', 'Microsoft.PowerAutomateDesktop_', 'Microsoft.Todos_', 'Microsoft.WindowsAlarms_', 'microsoft.windowscommunicationsapps_', 'Microsoft.WindowsFeedbackHub_', 'Microsoft.WindowsMaps_', 'Microsoft.WindowsSoundRecorder_', 'Microsoft.Xbox.TCUI_', 'Microsoft.XboxGamingOverlay_', 'Microsoft.XboxGameOverlay_', 'Microsoft.XboxSpeechToTextOverlay_', 'Microsoft.YourPhone_', 'Microsoft.ZuneMusic_', 'Microsoft.ZuneVideo_', 'MicrosoftCorporationII.MicrosoftFamily_', 'MicrosoftCorporationII.QuickAssist_', 'MicrosoftTeams_', 'Microsoft.549981C3F5F10_' $packagesToRemove = $packages | Where-Object { @@ -144,11 +143,12 @@ $packagesToRemove = $packages | Where-Object { $packagePrefixes -contains ($packagePrefixes | Where-Object { $packageName -like "$_*" }) } foreach ($package in $packagesToRemove) { - & 'dism' '/English' "/image:$($ScratchDisk)\scratchdir" '/Remove-ProvisionedAppxPackage' "/PackageName:$package" + Write-Host "Removing $package..." + Remove-AppxProvisionedPackage -Path "$ScratchDisk\scratchdir" -PackageName "$package" | Out-Null } -Write-Host "Removing Edge:" +Write-Host "`nRemoving Edge:" Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\Edge" -Recurse -Force | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeUpdate" -Recurse -Force | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Program Files (x86)\Microsoft\EdgeCore" -Recurse -Force | Out-Null @@ -388,10 +388,9 @@ Write-Host ' ' Write-Host "Unmounting image..." Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save Write-Host "Exporting image..." -# Compressiontype Recovery is not supported with PShell https://learn.microsoft.com/en-us/powershell/module/dism/export-windowsimage?view=windowsserver2022-ps#-compressiontype -Export-WindowsImage -SourceImagePath $ScratchDisk\tiny11\sources\install.wim -SourceIndex $index -DestinationImagePath $ScratchDisk\tiny11\sources\install2.wim -CompressionType Fast +# Compressiontype Recovery is not supported with PShell https://learn.microsoft.com/en-us/powershell/module/dism/export-windowsimage?-ps#-compressiontype +& dism /English /Export-Image "/SourceImageFile:$ScratchDisk\tiny11\sources\install.wim" "/SourceIndex:$index" "/DestinationImageFile:$ScratchDisk\tiny11\sources\install.esd" /Compress:recovery Remove-Item -Path "$ScratchDisk\tiny11\sources\install.wim" -Force | Out-Null -Rename-Item -Path "$ScratchDisk\tiny11\sources\install2.wim" -NewName "install.wim" | Out-Null Write-Host "Windows image completed. Continuing with boot.wim." Start-Sleep -Seconds 2 Clear-Host @@ -436,22 +435,32 @@ Write-Host "The tiny11 image is now completed. Proceeding with the making of the Write-Host "Copying unattended file for bypassing MS account on OOBE..." Copy-Item -Path "$PSScriptRoot\autounattend.xml" -Destination "$ScratchDisk\tiny11\autounattend.xml" -Force | Out-Null Write-Host "Creating ISO image..." -$ADKDepTools = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture\Oscdimg" +# 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 ([System.IO.Directory]::Exists($ADKDepTools)) { +if ((Test-Path variable:ADKDepTools) -and (Test-Path -Path "$ADKDepTools\oscdimg.exe" -PathType Leaf)) { Write-Host "Will be using oscdimg.exe from system ADK." $OSCDIMG = "$ADKDepTools\oscdimg.exe" } else { - Write-Host "ADK folder not found. Will be using bundled oscdimg.exe." + 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 (-not (Test-Path -Path $localOSCDIMGPath)) { + if (-not (Test-Path -Path $localOSCDIMGPath -PathType Leaf)) { Write-Host "Downloading oscdimg.exe..." Invoke-WebRequest -Uri $url -OutFile $localOSCDIMGPath - if (Test-Path $localOSCDIMGPath) { + if (Test-Path -Path $localOSCDIMGPath -PathType Leaf) { Write-Host "oscdimg.exe downloaded successfully." } else { Write-Error "Failed to download oscdimg.exe."