<# .SYNOPSIS Removes pre-installed bloatware: AppX packages, Capabilities, and Optional Features. .DESCRIPTION Removes Microsoft-bundled apps and features not needed in a business MSP deployment. Removal is done for all users (-AllUsers) and from the provisioning store so new users do not get them either. Calculator is intentionally kept. .ITEMS appx-balicky-odstraneni-pro-vsechny-uziv: Uses Remove-AppxPackage -AllUsers and Remove-AppxProvisionedPackage. The provisioned removal prevents apps from reinstalling for new user profiles. Covers ~35 apps including Cortana, Copilot, Teams personal, Xbox, Skype, News, Weather, Maps. zachovano-microsoft-windowscalculator: Calculator is explicitly excluded. Lightweight utility frequently used by technicians and end users. Removing it would require manual reinstall from Store. windows-capabilities-fax-ie-openssh-wmp-: Removed via Remove-WindowsCapability: Fax & Scan, Internet Explorer mode, OpenSSH client, Windows Media Player (legacy), WordPad, Handwriting recognition, Steps Recorder, Math Input Panel, Quick Assist. windows-optional-features-ps-2-0-mediapl: Disabled via Disable-WindowsOptionalFeature: PowerShell 2.0 (security risk - allows unsigned script execution bypass on older hosts), MediaPlayback, Windows Recall (AI screenshot surveillance), Snipping Tool optional component. feature-toggles: Three GUI feature flags gate removal. standardBloatware (default on) covers the bulk list. removeNewOutlook (default on) controls Microsoft.OutlookForWindows; classic Outlook from M365 is a Win32 app and is never touched. removeSnippingTool (default OFF) controls Snipping Tool across all three lists (ScreenSketch app + legacy capability + legacy feature) - kept by default as a common productivity tool, like Calculator. #> param( [string]$ConfigPath, [string]$LogFile ) . "$PSScriptRoot\common.ps1" $Config = Load-Config $ConfigPath # ----------------------------------------------------------------------- # Feature flags (see CLAUDE.md features system) # standardBloatware - removes the bulk AppX/capability/feature list # removeNewOutlook - new Outlook for Windows (Microsoft.OutlookForWindows) # removeSnippingTool - Snipping Tool, spans all three lists; default OFF # Outlook and Snipping items are gated by their own flag, independent of the # standard flag, so each GUI checkbox does exactly what it says. # ----------------------------------------------------------------------- $DoStandard = Get-Feature $Config "bloatware" "standardBloatware" $true $DoOutlook = Get-Feature $Config "bloatware" "removeNewOutlook" $true $DoSnipping = Get-Feature $Config "bloatware" "removeSnippingTool" $false # Snipping Tool appears as an AppX package (ScreenSketch, the modern app), # a legacy capability, and a legacy optional feature. $SnippingItems = @( "Microsoft.ScreenSketch" "Microsoft.Windows.SnippingTool" "Microsoft-SnippingTool" ) function Test-RemovalAllowed { param([string]$Name) if ($Name -eq "Microsoft.OutlookForWindows") { return $DoOutlook } if ($SnippingItems -contains $Name) { return $DoSnipping } return $DoStandard } # ----------------------------------------------------------------------- # 1a - AppX packages # ----------------------------------------------------------------------- $AppxToRemove = @( "Microsoft.Microsoft3DViewer" "Microsoft.BingSearch" "Microsoft.WindowsCamera" "Clipchamp.Clipchamp" "Microsoft.WindowsAlarms" "Microsoft.Copilot" "Microsoft.549981C3F5F10" "Microsoft.Windows.DevHome" "MicrosoftCorporationII.MicrosoftFamily" "Microsoft.WindowsFeedbackHub" "Microsoft.Edge.GameAssist" "Microsoft.GetHelp" "Microsoft.Getstarted" "microsoft.windowscommunicationsapps" "Microsoft.WindowsMaps" "Microsoft.MixedReality.Portal" "Microsoft.BingNews" "Microsoft.MicrosoftOfficeHub" "Microsoft.Office.OneNote" "Microsoft.OutlookForWindows" "Microsoft.Paint" "Microsoft.MSPaint" "Microsoft.People" "Microsoft.Windows.Photos" "Microsoft.PowerAutomateDesktop" "MicrosoftCorporationII.QuickAssist" "Microsoft.SkypeApp" "Microsoft.ScreenSketch" "Microsoft.MicrosoftSolitaireCollection" "Microsoft.MicrosoftStickyNotes" "MicrosoftTeams" "MSTeams" "Microsoft.Todos" "Microsoft.WindowsSoundRecorder" "Microsoft.Wallet" "Microsoft.BingWeather" "Microsoft.WindowsTerminal" "Microsoft.Xbox.TCUI" "Microsoft.XboxApp" "Microsoft.XboxGameOverlay" "Microsoft.XboxGamingOverlay" "Microsoft.XboxIdentityProvider" "Microsoft.XboxSpeechToTextOverlay" "Microsoft.GamingApp" "Microsoft.YourPhone" "Microsoft.ZuneMusic" "Microsoft.ZuneVideo" "7EE7776C.LinkedInforWindows" ) # Packages to always keep $KeepPackages = @("Microsoft.WindowsCalculator") if ($Config -and $Config.bloatware -and $Config.bloatware.keepPackages) { $KeepPackages += $Config.bloatware.keepPackages } $KeepPackages = $KeepPackages | Select-Object -Unique Write-Log "1a - Removing AppX packages" -Level STEP foreach ($pkg in $AppxToRemove) { if ($KeepPackages -contains $pkg) { Write-Log " KEEP $pkg" -Level INFO continue } if (-not (Test-RemovalAllowed $pkg)) { Write-Log " KEEP (feature off): $pkg" -Level INFO continue } # Installed packages (current user + all users) $installed = Get-AppxPackage -Name $pkg -AllUsers -ErrorAction SilentlyContinue if ($installed) { try { $installed | Remove-AppxPackage -AllUsers -ErrorAction Stop Write-Log " Removed AppxPackage: $pkg" -Level OK } catch { Write-Log " Failed to remove AppxPackage $pkg - $_" -Level WARN } } # Provisioned packages (for new users) $provisioned = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $pkg } if ($provisioned) { try { $provisioned | Remove-AppxProvisionedPackage -Online -ErrorAction Stop | Out-Null Write-Log " Removed provisioned: $pkg" -Level OK } catch { Write-Log " Failed to remove provisioned $pkg - $_" -Level WARN } } if (-not $installed -and -not $provisioned) { Write-Log " Not found (already removed): $pkg" -Level INFO } } # ----------------------------------------------------------------------- # 1b - Windows Capabilities # ----------------------------------------------------------------------- $CapabilitiesToRemove = @( "Print.Fax.Scan" "Language.Handwriting" "Browser.InternetExplorer" "MathRecognizer" "OneCoreUAP.OneSync" "OpenSSH.Client" "Microsoft.Windows.MSPaint" "Microsoft.Windows.PowerShell.ISE" "App.Support.QuickAssist" "Microsoft.Windows.SnippingTool" "App.StepsRecorder" "Hello.Face" "Media.WindowsMediaPlayer" "Microsoft.Windows.WordPad" ) Write-Log "1b - Removing Windows Capabilities" -Level STEP $installedCaps = Get-WindowsCapability -Online -ErrorAction SilentlyContinue foreach ($cap in $CapabilitiesToRemove) { if (-not (Test-RemovalAllowed $cap)) { Write-Log " KEEP (feature off): $cap" -Level INFO continue } # Match by prefix (e.g. Hello.Face matches Hello.Face.20134.0.0.0) $matches = $installedCaps | Where-Object { $_.Name -like "$cap*" -and $_.State -eq "Installed" } if ($matches) { foreach ($c in $matches) { try { Remove-WindowsCapability -Online -Name $c.Name -ErrorAction Stop | Out-Null Write-Log " Removed capability: $($c.Name)" -Level OK } catch { Write-Log " Failed to remove capability $($c.Name) - $_" -Level WARN } } } else { Write-Log " Not found or not installed: $cap" -Level INFO } } # ----------------------------------------------------------------------- # 1c - Windows Optional Features # ----------------------------------------------------------------------- $FeaturesToDisable = @( "MediaPlayback" "MicrosoftWindowsPowerShellV2Root" "Recall" "Microsoft-SnippingTool" ) Write-Log "1c - Disabling Windows Optional Features" -Level STEP foreach ($feat in $FeaturesToDisable) { if (-not (Test-RemovalAllowed $feat)) { Write-Log " KEEP (feature off): $feat" -Level INFO continue } $feature = Get-WindowsOptionalFeature -Online -FeatureName $feat -ErrorAction SilentlyContinue if ($feature -and $feature.State -eq "Enabled") { try { Disable-WindowsOptionalFeature -Online -FeatureName $feat -NoRestart -ErrorAction Stop | Out-Null Write-Log " Disabled feature: $feat" -Level OK } catch { Write-Log " Failed to disable feature $feat - $_" -Level WARN } } else { Write-Log " Not enabled or not found: $feat" -Level INFO } } Write-Log "Step 1 complete" -Level OK