# Requires running as administrator # Removes selected built-in Appx packages without winget. # Installed packages are removed for existing users when supported. # Provisioned packages are removed so they are not installed for new users. [CmdletBinding(SupportsShouldProcess = $true)] param( [switch]$IncludeOneDrive ) $ErrorActionPreference = "Continue" $IsAdministrator = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) if (-not $IsAdministrator) { Write-Error "This script must be run from an administrator PowerShell session." exit 1 } $PackageNamePatterns = @( "MicrosoftWindows.Client.WebExperience", "Microsoft.OutlookForWindows", "Microsoft.WindowsFeedbackHub", "Microsoft.XboxApp", "Microsoft.GamingApp", "Microsoft.Xbox.TCUI", "Microsoft.XboxGameOverlay", "Microsoft.XboxGamingOverlay", "Microsoft.XboxIdentityProvider", "Microsoft.XboxSpeechToTextOverlay", "Microsoft.PowerAutomateDesktop", "Microsoft.MicrosoftStickyNotes", "Microsoft.BingWeather", "MSTeams", "MicrosoftTeams", "Microsoft.Todos", "Microsoft.BingSearch", "Microsoft.BingNews", "Clipchamp.Clipchamp" ) $KnownPackageFamilyNames = @( "MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy", "Microsoft.OutlookForWindows_8wekyb3d8bbwe", "Microsoft.WindowsFeedbackHub_8wekyb3d8bbwe", "Microsoft.XboxApp_8wekyb3d8bbwe", "Microsoft.GamingApp_8wekyb3d8bbwe", "Microsoft.Xbox.TCUI_8wekyb3d8bbwe", "Microsoft.XboxGameOverlay_8wekyb3d8bbwe", "Microsoft.XboxGamingOverlay_8wekyb3d8bbwe", "Microsoft.XboxIdentityProvider_8wekyb3d8bbwe", "Microsoft.XboxSpeechToTextOverlay_8wekyb3d8bbwe", "Microsoft.PowerAutomateDesktop_8wekyb3d8bbwe", "Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe", "Microsoft.BingWeather_8wekyb3d8bbwe", "MSTeams_8wekyb3d8bbwe", "MicrosoftTeams_8wekyb3d8bbwe", "Microsoft.Todos_8wekyb3d8bbwe", "Microsoft.BingSearch_8wekyb3d8bbwe", "Microsoft.BingNews_8wekyb3d8bbwe", "Clipchamp.Clipchamp_yxz26nhyzhsrt" ) $Script:PackageFamilyNamesToBlock = @() function Add-PackageFamilyNameToBlockList { param( [string]$PackageFamilyName ) if ([string]::IsNullOrWhiteSpace($PackageFamilyName)) { return } if ($Script:PackageFamilyNamesToBlock -notcontains $PackageFamilyName) { $Script:PackageFamilyNamesToBlock += $PackageFamilyName } } function Get-PackageFamilyNameFromProvisionedPackage { param( [Parameter(Mandatory = $true)] $Package ) $Parts = $Package.PackageName -split "_" if ($Parts.Count -lt 2) { return $null } $PublisherId = $Parts[-1] return "$($Package.DisplayName)_$PublisherId" } function Invoke-InstalledAppxPackageRemoval { param( [string]$Pattern ) $Packages = Get-AppxPackage -AllUsers -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "*$Pattern*" -or $_.PackageFamilyName -like "*$Pattern*" } if (-not $Packages) { Write-Host "No installed Appx package found for: $Pattern" -ForegroundColor DarkGray return } foreach ($Package in $Packages) { Add-PackageFamilyNameToBlockList -PackageFamilyName $Package.PackageFamilyName $Target = "$($Package.Name) [$($Package.PackageFullName)]" Write-Host "Removing installed package: $Target" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($Target, "Remove installed Appx package")) { try { Remove-AppxPackage -Package $Package.PackageFullName -AllUsers -ErrorAction Stop Write-Host "Removed installed package: $($Package.Name)" -ForegroundColor Green } catch { Write-Warning "Failed to remove installed package $($Package.Name): $_" } } } } function Invoke-ProvisionedAppxPackageRemoval { param( [string]$Pattern ) $ProvisionedPackages = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -like "*$Pattern*" -or $_.PackageName -like "*$Pattern*" } if (-not $ProvisionedPackages) { Write-Host "No provisioned Appx package found for: $Pattern" -ForegroundColor DarkGray return } foreach ($Package in $ProvisionedPackages) { Add-PackageFamilyNameToBlockList -PackageFamilyName (Get-PackageFamilyNameFromProvisionedPackage -Package $Package) $Target = "$($Package.DisplayName) [$($Package.PackageName)]" Write-Host "Removing provisioned package: $Target" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($Target, "Remove provisioned Appx package for future users")) { try { Remove-AppxProvisionedPackage -Online -PackageName $Package.PackageName -ErrorAction Stop | Out-Null Write-Host "Removed provisioned package: $($Package.DisplayName)" -ForegroundColor Green } catch { Write-Warning "Failed to remove provisioned package $($Package.DisplayName): $_" } } } } function Set-DWordValue { param( [string]$Path, [string]$Name, [int]$Value ) if (-not (Test-Path $Path)) { New-Item -Path $Path -Force | Out-Null } New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType DWord -Force | Out-Null } function Remove-RegistryValue { param( [string]$Path, [string]$Name ) if (-not (Test-Path $Path)) { return } $Property = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue if ($null -eq $Property) { return } Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction SilentlyContinue } function Set-ConsumerExperiencePolicies { $CloudContentPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" Write-Host "Disabling Microsoft consumer experiences policy..." -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($CloudContentPath, "Set CloudContent policies")) { Set-DWordValue -Path $CloudContentPath -Name "DisableWindowsConsumerFeatures" -Value 1 Set-DWordValue -Path $CloudContentPath -Name "DisableCloudOptimizedContent" -Value 1 Write-Host "Microsoft consumer experience policies configured." -ForegroundColor Green } } function Set-OneDrivePolicies { $WindowsOneDrivePolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" $OneDrivePolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" Write-Host "Disabling OneDrive for all users..." -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($WindowsOneDrivePolicyPath, "Set OneDrive disable policy")) { Set-DWordValue -Path $WindowsOneDrivePolicyPath -Name "DisableFileSyncNGSC" -Value 1 Set-DWordValue -Path $OneDrivePolicyPath -Name "PreventNetworkTrafficPreUserSignIn" -Value 1 Write-Host "OneDrive policies configured." -ForegroundColor Green } } function Set-ContentDeliveryManagerDefaults { param( [string]$RegistryRoot ) $ContentDeliveryPath = Join-Path $RegistryRoot "SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" $ValuesToDisable = @( "ContentDeliveryAllowed", "FeatureManagementEnabled", "OemPreInstalledAppsEnabled", "PreInstalledAppsEnabled", "PreInstalledAppsEverEnabled", "SilentInstalledAppsEnabled", "SubscribedContent-310093Enabled", "SubscribedContent-338387Enabled", "SubscribedContent-338388Enabled", "SubscribedContent-338389Enabled", "SubscribedContent-338393Enabled", "SubscribedContent-353694Enabled", "SubscribedContent-353696Enabled", "SystemPaneSuggestionsEnabled" ) Write-Host "Configuring ContentDeliveryManager defaults in: $RegistryRoot" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($RegistryRoot, "Disable ContentDeliveryManager app suggestions")) { foreach ($ValueName in $ValuesToDisable) { Set-DWordValue -Path $ContentDeliveryPath -Name $ValueName -Value 0 } Write-Host "ContentDeliveryManager defaults configured." -ForegroundColor Green } } function Remove-OneDriveStartupFromRegistryRoot { param( [string]$RegistryRoot ) $RunPath = Join-Path $RegistryRoot "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" $RunOncePath = Join-Path $RegistryRoot "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" Write-Host "Removing OneDrive startup entries in: $RegistryRoot" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($RegistryRoot, "Remove OneDrive startup registry entries")) { Remove-RegistryValue -Path $RunPath -Name "OneDrive" Remove-RegistryValue -Path $RunPath -Name "OneDriveSetup" Remove-RegistryValue -Path $RunOncePath -Name "OneDrive" Remove-RegistryValue -Path $RunOncePath -Name "OneDriveSetup" Write-Host "OneDrive startup entries removed where present." -ForegroundColor Green } } function Remove-OneDriveShortcutsFromDefaultProfile { $ShortcutPaths = @( (Join-Path $env:SystemDrive "Users\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk"), (Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\OneDrive.lnk") ) foreach ($ShortcutPath in $ShortcutPaths) { if (-not (Test-Path $ShortcutPath)) { continue } Write-Host "Removing OneDrive shortcut: $ShortcutPath" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($ShortcutPath, "Remove OneDrive shortcut")) { Remove-Item -Path $ShortcutPath -Force -ErrorAction SilentlyContinue } } } function Set-DefaultUserProfileDefaults { $DefaultUserHive = "Registry::HKEY_USERS\DefaultUser" $DefaultUserDat = Join-Path $env:SystemDrive "Users\Default\NTUSER.DAT" $HiveWasLoaded = $false if (-not (Test-Path $DefaultUserDat)) { Write-Warning "Default user hive not found: $DefaultUserDat" return } if (-not (Test-Path $DefaultUserHive)) { Write-Host "Loading default user registry hive..." -ForegroundColor Cyan & reg.exe load "HKU\DefaultUser" $DefaultUserDat | Out-Null if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to load default user registry hive." return } $HiveWasLoaded = $true } try { Set-ContentDeliveryManagerDefaults -RegistryRoot $DefaultUserHive Remove-OneDriveStartupFromRegistryRoot -RegistryRoot $DefaultUserHive } finally { if ($HiveWasLoaded) { Write-Host "Unloading default user registry hive..." -ForegroundColor Cyan & reg.exe unload "HKU\DefaultUser" | Out-Null if ($LASTEXITCODE -ne 0) { Write-Warning "Failed to unload default user registry hive. Close registry tools and retry." } } } Remove-OneDriveShortcutsFromDefaultProfile } function Set-AppxDeprovisionedRegistryMarkers { param( [string[]]$PackageFamilyNames ) $DeprovisionedPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Deprovisioned" $PolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Appx\RemoveDefaultMicrosoftStorePackages" if (-not $PackageFamilyNames) { return } Write-Host "Writing Appx deprovisioning registry markers..." -ForegroundColor Cyan foreach ($PackageFamilyName in ($PackageFamilyNames | Sort-Object -Unique)) { if ($PSCmdlet.ShouldProcess($PackageFamilyName, "Block Appx provisioning for future users")) { New-Item -Path (Join-Path $DeprovisionedPath $PackageFamilyName) -Force | Out-Null Set-DWordValue -Path (Join-Path $PolicyPath $PackageFamilyName) -Name "RemovePackage" -Value 1 Write-Host "Blocked future provisioning: $PackageFamilyName" -ForegroundColor Green } } } function Invoke-OneDriveRemoval { $Installers = @( "$env:SystemRoot\System32\OneDriveSetup.exe", "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" ) foreach ($Installer in $Installers) { if (-not (Test-Path $Installer)) { continue } Write-Host "Removing OneDrive with: $Installer" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess($Installer, "Uninstall OneDrive")) { try { Start-Process -FilePath $Installer -ArgumentList "/uninstall" -Wait -NoNewWindow Write-Host "OneDrive uninstall command completed." -ForegroundColor Green } catch { Write-Warning "Failed to uninstall OneDrive with $Installer`: $_" } } } } Write-Host "Removing selected built-in Appx applications..." -ForegroundColor Cyan Write-Host "This can affect existing users and the default package set for new users." -ForegroundColor Yellow Write-Host "" foreach ($PackageFamilyName in $KnownPackageFamilyNames) { Add-PackageFamilyNameToBlockList -PackageFamilyName $PackageFamilyName } Set-ConsumerExperiencePolicies Set-OneDrivePolicies Set-ContentDeliveryManagerDefaults -RegistryRoot "HKCU:" Remove-OneDriveStartupFromRegistryRoot -RegistryRoot "HKCU:" Set-DefaultUserProfileDefaults foreach ($Pattern in $PackageNamePatterns) { Invoke-InstalledAppxPackageRemoval -Pattern $Pattern Invoke-ProvisionedAppxPackageRemoval -Pattern $Pattern Write-Host "" } Set-AppxDeprovisionedRegistryMarkers -PackageFamilyNames $Script:PackageFamilyNamesToBlock if ($IncludeOneDrive) { Invoke-OneDriveRemoval } else { Write-Host "OneDrive was not removed. Re-run with -IncludeOneDrive to call the built-in OneDrive uninstaller." -ForegroundColor Yellow } Write-Host "" Write-Host "Done. Restart Windows before creating new user profiles." -ForegroundColor Green