# Ensure script is run as Administrator
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Error "Run this script as Administrator."
exit
}
Write-Output "`n=== Installing Winget Packages ===`n"
$packages = @(
# Microsoft Tools
"Microsoft.VisualStudioCode",
"Microsoft.PowerToys",
"Microsoft.WindowsTerminal",
"Microsoft.AppInstaller",
"Microsoft.EdgeDriver",
"EdgeWebView2Runtime",
"Microsoft.OpenJDK.21",
"Microsoft.PCManager.Beta",
"Microsoft.PowerShell",
"Microsoft.RemoteDesktopClient",
"Microsoft.RemoteHelp",
"Microsoft.Sysinternals.PsTools",
"Microsoft.Sysinternals.Suite",
"Microsoft.UI.Xaml.2.7",
"Microsoft.UI.Xaml.2.8",
"Microsoft.VSTOR",
"Microsoft.WindowsAppRuntime.1.7",
"Microsoft.WindowsApplicationDriver",
"Microsoft.WindowsPCHealthCheck",
"Microsoft.bitsmanager",
"9WZDNCRD29V9",
# Visual C++ Redistributables
"Microsoft.VCRedist.2005.x64",
"Microsoft.VCRedist.2005.x86",
"Microsoft.VCRedist.2008.x64",
"Microsoft.VCRedist.2008.x86",
"Microsoft.VCRedist.2010.x64",
"Microsoft.VCRedist.2010.x86",
"Microsoft.VCRedist.2012.x64",
"Microsoft.VCRedist.2012.x86",
"Microsoft.VCRedist.2013.x64",
"Microsoft.VCRedist.2013.x86",
"Microsoft.VCRedist.2015+.x64",
"Microsoft.VCRedist.2015+.x86",
# ASP.NET Core Runtimes
"Microsoft.DotNet.AspNetCore.2_1",
"Microsoft.DotNet.AspNetCore.3_1",
"Microsoft.DotNet.AspNetCore.5",
"Microsoft.DotNet.AspNetCore.6",
"Microsoft.DotNet.AspNetCore.7",
"Microsoft.DotNet.AspNetCore.8",
"Microsoft.DotNet.AspNetCore.9",
"Microsoft.DotNet.AspNetCore.Preview",
# Windows Desktop Runtimes
"Microsoft.DotNet.DesktopRuntime.3_1",
"Microsoft.DotNet.DesktopRuntime.5",
"Microsoft.DotNet.DesktopRuntime.6",
"Microsoft.DotNet.DesktopRuntime.7",
"Microsoft.DotNet.DesktopRuntime.8",
"Microsoft.DotNet.DesktopRuntime.9",
"Microsoft.DotNet.DesktopRuntime.Preview",
# .NET Core Runtimes
"Microsoft.DotNet.Runtime.3_1",
"Microsoft.DotNet.Runtime.5",
"Microsoft.DotNet.Runtime.6",
"Microsoft.DotNet.Runtime.7",
"Microsoft.DotNet.Runtime.8",
"Microsoft.DotNet.Runtime.9",
"Microsoft.DotNet.Runtime.Preview",
# Other Utilities
"CodecGuide.K-LiteCodecPack.Standard",
"BleachBit.BleachBit",
"Piriform.CCleaner.Slim",
"LibreOffice.LibreOffice",
"Foxit.FoxitReader",
"Microsoft.Teams",
"Zoom.Zoom",
"Mozilla.Firefox",
"VideoLAN.VLC",
"7zip.7zip",
"ShareX.ShareX",
"Notepad++.Notepad++",
"Winaero.WinaeroTweaker",
"GIMP.GIMP.3"
# Placeholder entries—review before use
# "App.ID",
# "App.ID",
# "App.ID"
)
foreach ($package in $packages) {
Write-Output "Installing: $package"
winget install --id $package --silent --accept-package-agreements --accept-source-agreements --scope machine
}
Write-Output "`n=== Removing Superfluous Apps ===`n"
$appsToRemove = @(
"Microsoft.XboxApp",
"Microsoft.XboxGameOverlay",
"Microsoft.XboxGamingOverlay",
"Microsoft.XboxIdentityProvider",
"Microsoft.XboxSpeechToTextOverlay",
"Microsoft.YourPhone",
"Microsoft.ZuneMusic",
"Microsoft.ZuneVideo",
"Microsoft.People",
"Microsoft.SkypeApp",
"Microsoft.GetHelp",
"Microsoft.Getstarted",
"Microsoft.Messaging",
"Microsoft.MixedReality.Portal",
"Microsoft.WindowsMaps",
"Microsoft.WindowsFeedbackHub",
"Microsoft.BingNews",
"Microsoft.Whiteboard",
"Microsoft.Clipchamp"
)
foreach ($app in $appsToRemove) {
Write-Output "Uninstalling for all users: $app"
Get-AppxPackage -AllUsers -Name $app | Remove-AppxPackage
}
foreach ($app in $appsToRemove) {
Write-Output "Removing provisioned package: $app"
Get-AppxProvisionedPackage -Online | Where-Object DisplayName -EQ $app | Remove-AppxProvisionedPackage -Online
}
Write-Output "`n=== Disabling Consumer Features and Stub Apps ===`n"
# Disable consumer features
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Force | Out-Null
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableConsumerFeatures" -Value 1 -PropertyType DWORD -Force | Out-Null
# Remove stub app shortcuts
$startMenuPath = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs"
Get-ChildItem $startMenuPath -Filter *.lnk | Where-Object { $_.Name -match "LinkedIn|TikTok|Instagram|Spotify|Disney|Prime" } | Remove-Item -Force
Write-Output "Disabling Store app suggestions..."
$storePolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsStore"
# Create the key if it doesn't exist
if (-not (Test-Path $storePolicyPath)) {
New-Item -Path $storePolicyPath -Force | Out-Null
Write-Output "Created missing registry key: $storePolicyPath"
}
# Set the DisableStoreApps value
New-ItemProperty -Path $storePolicyPath -Name "DisableStoreApps" -Value 1 -PropertyType DWORD -Force | Out-Null
Write-Output "Store app suggestions disabled."
Write-Output "`n=== Enabling WSL and Installing Ubuntu ===`n"
# Enable WSL features
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
# Install WSL and Ubuntu
Write-Output "Installing WSL and Ubuntu..."
# wsl --install -d Ubuntu
Write-Output "`n=== Detecting Highest Available Ubuntu Version for WSL ==="
# Get list of online WSL distributions
$wslList = wsl.exe --list --online | Select-String "Ubuntu"
# Extract distro names
$ubuntuDistros = $wslList | ForEach-Object {
($_ -split '\s{2,}')[0].Trim()
} | Where-Object { $_ -match "^Ubuntu" }
# Parse version numbers and select highest
$latestUbuntu = $ubuntuDistros | Sort-Object {
if ($_ -match "Ubuntu-(\d+)\.(\d+)") {
[version]("$($matches[1]).$($matches[2])")
} else {
[version]"0.0"
}
} -Descending | Select-Object -First 1
if ($latestUbuntu) {
Write-Output "Installing: $latestUbuntu"
wsl.exe --install -d $latestUbuntu
} else {
Write-Warning "No Ubuntu versions found in WSL list."
}
Start-Sleep -Seconds 30
Write-Output "Initializing Ubuntu..."
wsl -d Ubuntu -- echo "Ubuntu initialized."
# Install recommended packages inside Ubuntu
Write-Output "Installing packages inside Ubuntu..."
wsl -d Ubuntu -- bash -c "
sudo apt update &&
sudo apt install -y gnome-terminal x11-apps firefox gedit build-essential curl git"
Write-Output "`n=== Applying UI and Power Settings ===`n"
# Disable Taskbar Widgets and Search Box
Write-Output "Disabling Taskbar Widgets and Search Box..."
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarDa" -Value 0 -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" -Name "SearchboxTaskbarMode" -Value 0 -PropertyType DWORD -Force | Out-Null
Write-Output "Disabling Taskbar Widgets and Search Box..."
# Disable Widgets
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v TaskbarDa /t REG_DWORD /d 0 /f
# Disable Search Box
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Search" /v SearchboxTaskbarMode /t REG_DWORD /d 0 /f
# Unpin Microsoft Store from Taskbar (if present)
Write-Output "Attempting to unpin Microsoft Store from Taskbar..."
$storeAppId = "Microsoft.WindowsStore_8wekyb3d8bbwe!App"
$taskbarPath = "$env:APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
Get-ChildItem $taskbarPath -Filter *.lnk | Where-Object { $_.Name -match "Store" } | Remove-Item -Force
# Set Desktop Background to Solid Dark Gray
Write-Output "Setting desktop background to solid dark gray..."
Set-ItemProperty -Path "HKCU:\Control Panel\Colors" -Name "Background" -Value "105 105 105"
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "Wallpaper" -Value ""
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "WallpaperStyle" -Value "0"
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "TileWallpaper" -Value "0"
# Disable Transparency Effects
Write-Output "Disabling transparency effects..."
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" -Name "EnableTransparency" -Value 0 -PropertyType DWORD -Force | Out-Null
# Disable Lock Screen Bing Images and Widgets
Write-Output "Disabling lock screen Bing images and widgets..."
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "RotatingLockScreenEnabled" -Value 0 -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338387Enabled" -Value 0 -PropertyType DWORD -Force | Out-Null
# Disable File Explorer Recommendations and Jump List History
Write-Output "Disabling File Explorer recent files and jump list history..."
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer" -Name "ShowRecent" -Value 0 -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer" -Name "ShowFrequent" -Value 0 -PropertyType DWORD -Force | Out-Null
Write-Output "Disabling tips and account notifications..."
# Disable tips/promotions from ContentDeliveryManager
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-310093Enabled" -Value 0 -PropertyType DWORD Force
# Disable account-related toast notifications (create key if missing)
$toastBaseKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings"
$toastSubKey = "Windows.SystemToast.Account"
$toastFullPath = "$toastBaseKey\$toastSubKey"
if (-not (Test-Path $toastFullPath)) {
Write-Output "Creating missing registry key: $toastFullPath"
New-Item -Path $toastBaseKey -Name $toastSubKey -Force
}
Write-Output "Disabling account-related toast notifications..."
# Disable Snap Windows
Write-Output "Disabling Snap Windows..."
New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "WindowArrangementActive" -Value 0 -PropertyType String -Force | Out-Null
# Enable Storage Sense Weekly
Write-Output "Enabling Storage Sense to run weekly..."
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy" -Name "StorageSenseEnabled" -Value 1 -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy" -Name "TaskFrequency" -Value 1 -PropertyType DWORD -Force | Out-Null
# Power Settings
Write-Output "Configuring power settings..."
# Plugged in
powercfg /change monitor-timeout-ac 60
powercfg /change standby-timeout-ac 0
powercfg /setacvalueindex SCHEME_CURRENT SUB_VIDEO VIDEOIDLE 1800
powercfg /setacvalueindex SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMAX 100
powercfg /setacvalueindex SCHEME_CURRENT SUB_ENERGYSAVER PERFLEVEL 100
# Battery
powercfg /change monitor-timeout-dc 3
powercfg /change standby-timeout-dc 5
powercfg /setdcvalueindex SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMAX 80
powercfg /setdcvalueindex SCHEME_CURRENT SUB_ENERGYSAVER PERFLEVEL 0
# Apply changes
powercfg /setactive SCHEME_CURRENT
# Enable Lock Screen Timeout (plugged in)
Write-Output "Setting lock screen timeout (plugged in)..."
New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "ScreenSaverIsSecure" -Value 1 -PropertyType String -Force | Out-Null
New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "ScreenSaveTimeOut" -Value "1800" -PropertyType String -Force | Out-Null
Write-Output "`n=== Running System Cleanup ===`n"
if (Test-Path "C:\Windows.old") { Remove-Item "C:\Windows.old" -Recurse -Force }
# Run Disk Cleanup silently using cleanmgr automation
Write-Output "Running Disk Cleanup (cleanmgr)..."
# Create automation config for all cleanup options
$cleanmgrSagePath = "$env:SystemRoot\System32\cleanmgr.exe"
$cleanmgrSageRun = "$env:SystemRoot\SageRunFlags.txt"
Write-Output "`n=== Preconfiguring Disk Cleanup Options ==="
$volumeCachesPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$cleanupKeys = Get-ChildItem $volumeCachesPath
foreach ($key in $cleanupKeys) {
try {
Set-ItemProperty -Path $key.PSPath -Name "StateFlags0001" -Value 2 -ErrorAction SilentlyContinue
Write-Output "Enabled cleanup for: $($key.PSChildName)"
} catch {
Write-Warning "Could not set cleanup flag for: $($key.PSChildName)"
}
}
Write-Output "`n=== Running Disk Cleanup Silently ==="
Start-Process -FilePath "$env:SystemRoot\System32\cleanmgr.exe" -ArgumentList "/SAGERUN:1" -Wait
# Run BleachBit CLI if available
$bleachbitPath = "${env:ProgramFiles(x86)}\BleachBit\bleachbit_console.exe"
$bblogPath = "$basePath\blchbitlog.txt"
if (Test-Path $bleachbitPath) {
Write-Output "Running BleachBit CLI cleanup..."
Start-Process -FilePath $bleachbitPath -ArgumentList "--clean --preset" -RedirectStandardOutput $bblogPath -RedirectStandardError $bblogPath -WindowStyle Hidden -Wait
} else {
Write-Warning "BleachBit CLI not found at expected path. Skipping BleachBit cleanup."
}
Write-Output "`n ---> System cleanup complete."
Write-Output "`n ---> New computer configuration complete. Initiating app and Windows updates.`n"
Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File 'C:\temp\Update-Apps-and-Windows.ps1'" -WindowStyle Normal
Write-Output "`n ---> New computer setup script complete.`n"
Write-Output "`n ---> Wait for updates to install.`n"
Write-Output "`n ---> Windows will automatically restart for updates if needed.`n"
# Ensure script is run as Administrator
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Error "Run this script as Administrator."
exit
}
Write-Output "**===== vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv =====**"
Write-Output "**===== =====**"
Write-Output "**--> Windows will auto-reboot for update installation <--**"
Write-Output "**===== Run this script again after reboot =====**"
Write-Output "**===== =====**"
Write-Output "**===== ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ =====**"
sleep 5
# Timestamp for logs: yyyy.MM.dd.HH.mm
$timestamp = (Get-Date).ToString("yyyy.MM.dd.HH.mm")
# Paths
$basePath = "C:\temp\windowsupdatelogs"
$logPath = "$basePath\archived-logs"
Write-Output "`n=== Preparing Log Directory ==="
# Create log directory if needed
if (-not (Test-Path $logPath)) {
New-Item -Path $logPath -ItemType Directory -Force | Out-Null
Write-Output "Created log directory: $logPath"
} else {
Write-Output "Log directory already exists: $logPath"
}
# Move previous update logs to archive
Write-Output "Archiving previous update logs..."
Get-ChildItem -Path $basePath -Filter "*WindowsUpdateInstall*.log" | Move-Item -Destination $logPath -Force
Get-ChildItem -Path $basePath -Filter "*WUList*.txt" | Move-Item -Destination $logPath -Force
Get-ChildItem -Path $basePath -Filter "*PSWindowsUpdateInstall*.log" | Move-Item -Destination $logPath -Force
# Upgrade all winget packages
Write-Output "`n=== Running Winget Upgrade ==="
winget upgrade --all --accept-package-agreements --accept-source-agreements
# Install PSWindowsUpdate module
Write-Output "`n=== Installing PSWindowsUpdate Module ==="
Install-Module -Name PSWindowsUpdate -Force -Verbose | Out-File "$basePath\PSWindowsUpdateInstall-$timestamp.log"
Import-Module PSWindowsUpdate -Verbose
# Reset Windows Update components
Write-Output "Resetting Windows Update components..."
Reset-WUComponents
Write-Output "`n=== Adding Windows Update Sources ==="
# Define known update sources with labels
$updateSources = @(
@{ ID = "7971f918-a847-4430-9279-4a52d1efe18d"; Name = "Microsoft Update" },
@{ ID = "8b24b027-1dee-babb-9a95-3517dfb9c552"; Name = "DCat Flighting Prod" },
@{ ID = "855e8a7c-ecb4-4ca3-b045-1dfa50104289"; Name = "Windows Store (DCat Prod)" },
@{ ID = "9482f4b4-e343-43b6-b170-9a65bc822c77"; Name = "Windows Update" }
)
foreach ($source in $updateSources) {
$id = $source.ID
$name = $source.Name
try {
Add-WUServiceManager -ServiceID $id -AddServiceFlag 7 -Confirm:$False -ErrorAction SilentlyContinue
$status = Get-WUServiceManager | Where-Object { $_.ServiceID -eq $id }
if ($status) {
$enabled = $status.IsDefaultAUService
$registered = $status.IsRegisteredWithAU
Write-Output "$id`t$enabled`t$registered`t$name"
} else {
Write-Warning "Could not retrieve status for: $name ($id)"
}
} catch {
Write-Warning "Failed to add update source: $name ($id)"
}
}
# Remove WSUS update source
# Write-Output "Removing WSUS update source..."
# Remove-WUServiceManager -ServiceID "9482f4b4-e343-43b6-b170-9a65bc822c77" -Confirm:$False
# Add update sources
Write-Output "`n=== Adding Update Sources ==="
foreach ($id in $serviceIDs) {
Write-Output "`n=== Adding Update Source $id ==="
Add-WUServiceManager -ServiceID $id -AddServiceFlag 7 -Confirm:$False
}
# Get update lists
Write-Output "`n=== Checking for Available Updates ==="
foreach ($id in $serviceIDs) {
Get-WUList -ServiceID $id -Verbose | Out-File "$basePath\WUList-$timestamp.txt"
}
Write-Output "`n=== Installing Updates and Checking Reboot Requirement ==="
# Run update and capture result
$updateResult = Install-WindowsUpdate -ServiceID $id -AcceptAll -Verbose -Confirm:$False -IgnoreReboot | Tee-Object -FilePath "$basePath\WindowsUpdateInstall-$timestamp.log"
# Check if reboot is required
if ($updateResult -match "Reboot Required: True") {
Write-Output "`n ===Updates require a reboot. System will restart in 90 seconds.==="
Start-Sleep -Seconds 90
Restart-Computer -Force
} else {
Write-Output "`n No reboot required after updates."
}
Write-Output "`n [|---> Windows Setup and Update process complete. Computer is ready for use. <---|]"