diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c084f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.log +scratchdir/ +tiny11/ diff --git a/tiny11maker.ps1 b/tiny11maker.ps1 index c24757f..1993791 100644 --- a/tiny11maker.ps1 +++ b/tiny11maker.ps1 @@ -12,6 +12,7 @@ .PARAMETER SCRATCH Drive letter of the desired scratch disk (eg: D) + NOTE: The SCRATCH drive must support file/folder security (i.e., must be, e.g., NTFS filesystem). .EXAMPLE .\tiny11maker.ps1 E D @@ -33,6 +34,10 @@ param ( [ValidatePattern('^[c-zC-Z]$')][string]$SCRATCH ) +$ErrorActionPreference = 'Stop' +$WarningPreference = 'Continue' +$InformationPreference = 'Continue' + if (-not $SCRATCH) { $ScratchDisk = $PSScriptRoot -replace '[\\]+$', '' } else { @@ -104,8 +109,9 @@ if (-not (Test-Path -Path "$PSScriptRoot/autounattend.xml")) { Start-Transcript -Path "$PSScriptRoot\tiny11_$(get-date -f yyyyMMdd_HHmms).log" $Host.UI.RawUI.WindowTitle = "Tiny11 image creator" + Clear-Host -Write-Output "Welcome to the tiny11 image creator! Release: 09-07-25" +Write-Output "=== Welcome to the tiny11 image creator! Release: 09-07-25" $hostArchitecture = $Env:PROCESSOR_ARCHITECTURE New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny11\sources" | Out-Null @@ -138,20 +144,23 @@ if ((Test-Path "$DriveLetter\sources\boot.wim") -eq $false -or (Test-Path "$Driv } } -Write-Output "Copying Windows image..." +Write-Output "=== Copying Windows image..." + Copy-Item -Path "$DriveLetter\*" -Destination "$ScratchDisk\tiny11" -Recurse -Force | Out-Null -Set-ItemProperty -Path "$ScratchDisk\tiny11\sources\install.esd" -Name IsReadOnly -Value $false > $null 2>&1 -Remove-Item "$ScratchDisk\tiny11\sources\install.esd" > $null 2>&1 +Set-ItemProperty -Path "$ScratchDisk\tiny11\sources\install.esd" -Name IsReadOnly -Value $false -ErrorAction 'Continue' > $null 2>&1 +Remove-Item "$ScratchDisk\tiny11\sources\install.esd" -ErrorAction 'Continue' > $null 2>&1 Write-Output "Copy complete!" Start-Sleep -Seconds 2 + Clear-Host -Write-Output "Getting image information:" +Write-Output "=== Getting image information:" $ImagesIndex = (Get-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim).ImageIndex while ($ImagesIndex -notcontains $index) { Get-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim $index = Read-Host "Please enter the image index" } -Write-Output "Mounting Windows image. This may take a while." + +Write-Output "=== Mounting Windows image. This may take a while." $wimFilePath = "$ScratchDisk\tiny11\sources\install.wim" & takeown "/F" $wimFilePath & icacls $wimFilePath "/grant" "$($adminGroup.Value):(F)" @@ -161,6 +170,7 @@ try { # This block will catch the error and suppress it. Write-Error "$wimFilePath not found" } + New-Item -ItemType Directory -Force -Path "$ScratchDisk\scratchdir" > $null Mount-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\install.wim -Index $index -Path $ScratchDisk\scratchdir @@ -193,7 +203,7 @@ if (-not $architecture) { Write-Output "Architecture information not found." } -Write-Output "Mounting complete! Performing removal of applications..." +Write-Output "=== Mounting complete! Performing removal of applications..." $packages = & 'dism' '/English' "/image:$($ScratchDisk)\scratchdir" '/Get-ProvisionedAppxPackages' | ForEach-Object { @@ -264,27 +274,29 @@ foreach ($package in $packagesToRemove) { & 'dism' '/English' "/image:$($ScratchDisk)\scratchdir" '/Remove-ProvisionedAppxPackage' "/PackageName:$package" } -Write-Output "Removing Edge:" +Write-Output "=== Removing 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 & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" '/r' | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Windows\System32\Microsoft-Edge-Webview" -Recurse -Force | Out-Null -Write-Output "Removing OneDrive:" + +Write-Output "=== Removing OneDrive:" & 'takeown' '/f' "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" | Out-Null & 'icacls' "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe" -Force | Out-Null Write-Output "Removal complete!" Start-Sleep -Seconds 2 -Clear-Host -Write-Output "Loading registry..." + +Write-Output "=== Loading registry..." reg load HKLM\zCOMPONENTS $ScratchDisk\scratchdir\Windows\System32\config\COMPONENTS | Out-Null reg load HKLM\zDEFAULT $ScratchDisk\scratchdir\Windows\System32\config\default | Out-Null reg load HKLM\zNTUSER $ScratchDisk\scratchdir\Users\Default\ntuser.dat | Out-Null reg load HKLM\zSOFTWARE $ScratchDisk\scratchdir\Windows\System32\config\SOFTWARE | Out-Null reg load HKLM\zSYSTEM $ScratchDisk\scratchdir\Windows\System32\config\SYSTEM | Out-Null -Write-Output "Bypassing system requirements(on the system image):" + +Write-Output "=== Bypassing system requirements (on the system image):" Set-RegistryValue 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0' @@ -295,7 +307,8 @@ Set-RegistryValue 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassSecureBootCheck' 'REG_DW Set-RegistryValue 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassStorageCheck' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassTPMCheck' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSYSTEM\Setup\MoSetup' 'AllowUpgradesWithUnsupportedTPMOrCPU' 'REG_DWORD' '1' -Write-Output "Disabling Sponsored Apps:" + +Write-Output "=== Disabling Sponsored Apps:" Set-RegistryValue 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'OemPreInstalledAppsEnabled' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'PreInstalledAppsEnabled' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' 'SilentInstalledAppsEnabled' 'REG_DWORD' '0' @@ -319,23 +332,29 @@ Remove-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Con Remove-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SuggestedApps' Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableConsumerAccountStateContent' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent' 'DisableCloudOptimizedContent' 'REG_DWORD' '1' -Write-Output "Enabling Local Accounts on OOBE:" + +Write-Output "=== Enabling Local Accounts on OOBE:" Set-RegistryValue 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' 'BypassNRO' 'REG_DWORD' '1' Copy-Item -Path "$PSScriptRoot\autounattend.xml" -Destination "$ScratchDisk\scratchdir\Windows\System32\Sysprep\autounattend.xml" -Force | Out-Null -Write-Output "Disabling Reserved Storage:" +Write-Output "=== Disabling Reserved Storage:" Set-RegistryValue 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager' 'ShippedWithReserves' 'REG_DWORD' '0' -Write-Output "Disabling BitLocker Device Encryption" + +Write-Output "=== Disabling BitLocker Device Encryption" Set-RegistryValue 'HKLM\zSYSTEM\ControlSet001\Control\BitLocker' 'PreventDeviceEncryption' 'REG_DWORD' '1' -Write-Output "Disabling Chat icon:" + +Write-Output "=== Disabling Chat icon:" Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat' 'ChatIcon' 'REG_DWORD' '3' Set-RegistryValue 'HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'TaskbarMn' 'REG_DWORD' '0' -Write-Output "Removing Edge related registries" + +Write-Output "=== Removing Edge related registries" Remove-RegistryValue "HKEY_LOCAL_MACHINE\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge" Remove-RegistryValue "HKEY_LOCAL_MACHINE\zSOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update" -Write-Output "Disabling OneDrive folder backup" + +Write-Output "=== Disabling OneDrive folder backup" Set-RegistryValue "HKLM\zSOFTWARE\Policies\Microsoft\Windows\OneDrive" "DisableFileSyncNGSC" "REG_DWORD" "1" -Write-Output "Disabling Telemetry:" + +Write-Output "=== Disabling Telemetry:" Set-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo' 'Enabled' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Windows\CurrentVersion\Privacy' 'TailoredExperiencesWithDiagnosticDataEnabled' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Speech_OneCore\Settings\OnlineSpeechPrivacy' 'HasAccepted' 'REG_DWORD' '0' @@ -347,72 +366,81 @@ Set-RegistryValue 'HKLM\zNTUSER\Software\Microsoft\Personalization\Settings' 'Ac Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' 'AllowTelemetry' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' 'Start' 'REG_DWORD' '4' ## Prevents installation of DevHome and Outlook -Write-Output "Prevents installation of DevHome and Outlook:" + +Write-Output "=== Prevents installation of DevHome and Outlook:" Set-RegistryValue 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate' 'workCompleted' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\DevHomeUpdate' 'workCompleted' 'REG_DWORD' '1' Remove-RegistryValue 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' Remove-RegistryValue 'HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate' -Write-Output "Disabling Copilot" + +Write-Output "=== Disabling Copilot" Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\WindowsCopilot' 'TurnOffWindowsCopilot' 'REG_DWORD' '1' Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Edge' 'HubsSidebarEnabled' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Explorer' 'DisableSearchBoxSuggestions' 'REG_DWORD' '1' -Write-Output "Prevents installation of Teams:" + +Write-Output "=== Prevents installation of Teams:" Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Teams' 'DisableInstallation' 'REG_DWORD' '1' -Write-Output "Prevent installation of New Outlook": + +Write-Output "=== Prevent installation of New Outlook:" Set-RegistryValue 'HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Mail' 'PreventRun' 'REG_DWORD' '1' -Write-Host "Deleting scheduled task definition files..." +Write-Host "=== Deleting scheduled task definition files..." $tasksPath = "$ScratchDisk\scratchdir\Windows\System32\Tasks" -# Application Compatibility Appraiser +Write-Host "=== Deleting Application Compatibility Appraiser" Remove-Item -Path "$tasksPath\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -Force -ErrorAction SilentlyContinue -# Customer Experience Improvement Program (removes the entire folder and all tasks within it) +Write-Host "=== Deleting Customer Experience Improvement Program (removes the entire folder and all tasks within it)" Remove-Item -Path "$tasksPath\Microsoft\Windows\Customer Experience Improvement Program" -Recurse -Force -ErrorAction SilentlyContinue -# Program Data Updater +Write-Host "=== Deleting Program Data Updater" Remove-Item -Path "$tasksPath\Microsoft\Windows\Application Experience\ProgramDataUpdater" -Force -ErrorAction SilentlyContinue -# Chkdsk Proxy +Write-Host "=== Deleting Chkdsk Proxy" Remove-Item -Path "$tasksPath\Microsoft\Windows\Chkdsk\Proxy" -Force -ErrorAction SilentlyContinue -# Windows Error Reporting (QueueReporting) +Write-Host "=== Deleting Windows Error Reporting (QueueReporting)" Remove-Item -Path "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force -ErrorAction SilentlyContinue Write-Host "Task files have been deleted." -Write-Host "Unmounting Registry..." + +Write-Host "=== Unmounting Registry..." reg unload HKLM\zCOMPONENTS | Out-Null reg unload HKLM\zDEFAULT | Out-Null reg unload HKLM\zNTUSER | Out-Null reg unload HKLM\zSOFTWARE | Out-Null reg unload HKLM\zSYSTEM | Out-Null -Write-Output "Cleaning up image..." + +Write-Output "=== Cleaning up image..." dism.exe /Image:$ScratchDisk\scratchdir /Cleanup-Image /StartComponentCleanup /ResetBase Write-Output "Cleanup complete." -Write-Output ' ' -Write-Output "Unmounting image..." + +Write-Output '' +Write-Output "=== Unmounting image..." Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save -Write-Host "Exporting image..." + +Write-Host "=== Exporting image..." Dism.exe /Export-Image /SourceImageFile:"$ScratchDisk\tiny11\sources\install.wim" /SourceIndex:$index /DestinationImageFile:"$ScratchDisk\tiny11\sources\install2.wim" /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-Output "Windows image completed. Continuing with boot.wim." Start-Sleep -Seconds 2 -Clear-Host -Write-Output "Mounting boot image:" + +Write-Output "=== Mounting boot image:" $wimFilePath = "$ScratchDisk\tiny11\sources\boot.wim" & takeown "/F" $wimFilePath | Out-Null & icacls $wimFilePath "/grant" "$($adminGroup.Value):(F)" Set-ItemProperty -Path $wimFilePath -Name IsReadOnly -Value $false Mount-WindowsImage -ImagePath $ScratchDisk\tiny11\sources\boot.wim -Index 2 -Path $ScratchDisk\scratchdir -Write-Output "Loading registry..." + +Write-Output "=== Loading registry..." reg load HKLM\zCOMPONENTS $ScratchDisk\scratchdir\Windows\System32\config\COMPONENTS reg load HKLM\zDEFAULT $ScratchDisk\scratchdir\Windows\System32\config\default reg load HKLM\zNTUSER $ScratchDisk\scratchdir\Users\Default\ntuser.dat reg load HKLM\zSOFTWARE $ScratchDisk\scratchdir\Windows\System32\config\SOFTWARE reg load HKLM\zSYSTEM $ScratchDisk\scratchdir\Windows\System32\config\SYSTEM -Write-Output "Bypassing system requirements(on the setup image):" +Write-Output "=== Bypassing system requirements(on the setup image):" Set-RegistryValue 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' 'SV2' 'REG_DWORD' '0' Set-RegistryValue 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' 'SV1' 'REG_DWORD' '0' @@ -425,20 +453,23 @@ Set-RegistryValue 'HKLM\zSYSTEM\Setup\LabConfig' 'BypassTPMCheck' 'REG_DWORD' '1 Set-RegistryValue 'HKLM\zSYSTEM\Setup\MoSetup' 'AllowUpgradesWithUnsupportedTPMOrCPU' 'REG_DWORD' '1' Write-Output "Tweaking complete!" -Write-Output "Unmounting Registry..." +Write-Output "=== Unmounting Registry..." reg unload HKLM\zCOMPONENTS | Out-Null reg unload HKLM\zDEFAULT | Out-Null reg unload HKLM\zNTUSER | Out-Null reg unload HKLM\zSOFTWARE | Out-Null reg unload HKLM\zSYSTEM | Out-Null -Write-Output "Unmounting image..." +Write-Output "=== Unmounting image..." Dismount-WindowsImage -Path $ScratchDisk\scratchdir -Save -Clear-Host + +Write-Output "========================================" Write-Output "The tiny11 image is now completed. Proceeding with the making of the ISO..." Write-Output "Copying unattended file for bypassing MS account on OOBE..." + Copy-Item -Path "$PSScriptRoot\autounattend.xml" -Destination "$ScratchDisk\tiny11\autounattend.xml" -Force | Out-Null -Write-Output "Creating ISO image..." + +Write-Output "=== Creating ISO image..." $ADKDepTools = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture\Oscdimg" $localOSCDIMGPath = "$PSScriptRoot\oscdimg.exe" @@ -471,18 +502,22 @@ if ([System.IO.Directory]::Exists($ADKDepTools)) { # Finishing up Write-Output "Creation completed! Press any key to exit the script..." Read-Host "Press Enter to continue" -Write-Output "Performing Cleanup..." + +Write-Output "=== Performing Cleanup..." Remove-Item -Path "$ScratchDisk\tiny11" -Recurse -Force | Out-Null Remove-Item -Path "$ScratchDisk\scratchdir" -Recurse -Force | Out-Null -Write-Output "Ejecting Iso drive" + +Write-Output "=== Ejecting Iso drive" Get-Volume -DriveLetter $DriveLetter[0] | Get-DiskImage | Dismount-DiskImage Write-Output "Iso drive ejected" -Write-Output "Removing oscdimg.exe..." + +Write-Output "=== Removing oscdimg.exe..." Remove-Item -Path "$PSScriptRoot\oscdimg.exe" -Force -ErrorAction SilentlyContinue -Write-Output "Removing autounattend.xml..." + +Write-Output "=== Removing autounattend.xml..." Remove-Item -Path "$PSScriptRoot\autounattend.xml" -Force -ErrorAction SilentlyContinue -Write-Output "Cleanup check :" +Write-Output "=== Cleanup check :" if (Test-Path -Path "$ScratchDisk\tiny11") { Write-Output "tiny11 folder still exists. Attempting to remove it again..." Remove-Item -Path "$ScratchDisk\tiny11" -Recurse -Force -ErrorAction SilentlyContinue @@ -494,6 +529,7 @@ if (Test-Path -Path "$ScratchDisk\tiny11") { } else { Write-Output "tiny11 folder does not exist. No action needed." } + if (Test-Path -Path "$ScratchDisk\scratchdir") { Write-Output "scratchdir folder still exists. Attempting to remove it again..." Remove-Item -Path "$ScratchDisk\scratchdir" -Recurse -Force -ErrorAction SilentlyContinue @@ -505,6 +541,7 @@ if (Test-Path -Path "$ScratchDisk\scratchdir") { } else { Write-Output "scratchdir folder does not exist. No action needed." } + if (Test-Path -Path "$PSScriptRoot\oscdimg.exe") { Write-Output "oscdimg.exe still exists. Attempting to remove it again..." Remove-Item -Path "$PSScriptRoot\oscdimg.exe" -Force -ErrorAction SilentlyContinue @@ -516,6 +553,7 @@ if (Test-Path -Path "$PSScriptRoot\oscdimg.exe") { } else { Write-Output "oscdimg.exe does not exist. No action needed." } + if (Test-Path -Path "$PSScriptRoot\autounattend.xml") { Write-Output "autounattend.xml still exists. Attempting to remove it again..." Remove-Item -Path "$PSScriptRoot\autounattend.xml" -Force -ErrorAction SilentlyContinue @@ -532,4 +570,3 @@ if (Test-Path -Path "$PSScriptRoot\autounattend.xml") { Stop-Transcript exit -