4 Commits

Author SHA1 Message Date
Jeffrey
0e7b289d03 Add Multi-tasking settings (#458)
- Disable window snapping
- Disable Snap Assist
- Disable Snap Layouts
- Change showing tabs when snapping or pressing Alt+Tab
2026-02-12 23:14:15 +01:00
Jeffrey
feef8f76b9 Add option to select target user(s) for app removal (#462) 2026-02-12 22:50:22 +01:00
Jeffrey
50db66bb5f Fix styling for other user input box (#459) 2026-02-11 22:27:50 +01:00
Raphire
b48fa24627 Improve DisableEdgeAds feature
This will now also disable:
- The first run experience
- Default browser prompts
- Adobe Acrobat buttons/ads
- Spotlight experiences and recommendations
2026-02-10 21:11:46 +01:00
25 changed files with 334 additions and 33 deletions

View File

@@ -9,6 +9,7 @@
"Taskbar",
"Appearance",
"File Explorer",
"Multi-tasking",
"Other",
"Gaming"
],
@@ -74,6 +75,18 @@
{ "Label": "Downloads", "FeatureIds": ["ExplorerToDownloads"] },
{ "Label": "OneDrive", "FeatureIds": ["ExplorerToOneDrive"] }
]
},
{
"GroupId": "ShowTabsInAltTab",
"Label": "Show tabs from apps when snapping or pressing Alt+Tab",
"Category": "Multi-tasking",
"Priority": 10,
"Values": [
{ "Label": "Don't show tabs", "FeatureIds": ["HideTabsInAltTab"] },
{ "Label": "Show 3 most recent tabs", "FeatureIds": ["Show3TabsInAltTab"] },
{ "Label": "Show 5 most recent tabs", "FeatureIds": ["Show5TabsInAltTab"] },
{ "Label": "Show 20 most recent tabs", "FeatureIds": ["Show20TabsInAltTab"] }
]
}
],
"Features": [
@@ -487,7 +500,7 @@
},
{
"FeatureId": "DisableStickyKeys",
"Label": "Sticky Keys keyboard shortcut",
"Label": "Sticky Keys keyboard shortcut (5x shift)",
"Category": "System",
"Action": "Disable",
"RegistryKey": "Disable_Sticky_Keys_Shortcut.reg",
@@ -497,6 +510,93 @@
"MinVersion": 26100,
"MaxVersion": null
},
{
"FeatureId": "DisableWindowSnapping",
"Label": "window snapping",
"Category": "Multi-tasking",
"Priority": 1,
"Action": "Disable",
"RegistryKey": "Disable_Window_Snapping.reg",
"ApplyText": "> Disabling window snapping...",
"UndoAction": "Enable",
"RegistryUndoKey": "Enable_Window_Snapping.reg",
"MinVersion": null,
"MaxVersion": null
},
{
"FeatureId": "DisableSnapAssist",
"Label": "showing app suggestions when snapping windows",
"Category": "Multi-tasking",
"Priority": 2,
"Action": "Disable",
"RegistryKey": "Disable_Snap_Assist.reg",
"ApplyText": "> Disabling the Snap Assist suggestions...",
"UndoAction": "Enable",
"RegistryUndoKey": "Enable_Snap_Assist.reg",
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "DisableSnapLayouts",
"Label": "snap layout flyout at top of screen and on maximize button",
"Category": "Multi-tasking",
"Priority": 3,
"Action": "Hide",
"RegistryKey": "Disable_Snap_Layouts.reg",
"ApplyText": "> Hiding snap layouts when dragging windows to top of the screen and on maximize button...",
"UndoAction": "Show",
"RegistryUndoKey": "Enable_Snap_Layouts.reg",
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "HideTabsInAltTab",
"Label": "tabs from apps when snapping or pressing Alt+Tab",
"Category": "Multi-tasking",
"Action": "Hide",
"RegistryKey": "Hide_Tabs_In_Alt_Tab.reg",
"ApplyText": "> Disable showing tabs from apps when snapping or pressing Alt+Tab...",
"UndoAction": null,
"RegistryUndoKey": null,
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "Show3TabsInAltTab",
"Label": "tabs from apps when snapping or pressing Alt+Tab",
"Category": "Multi-tasking",
"Action": "Show 3",
"RegistryKey": "Show_3_Tabs_In_Alt_Tab.reg",
"ApplyText": "> Enable showing 3 tabs from apps when snapping or pressing Alt+Tab...",
"UndoAction": null,
"RegistryUndoKey": null,
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "Show5TabsInAltTab",
"Label": "tabs from apps when snapping or pressing Alt+Tab",
"Category": "Multi-tasking",
"Action": "Show 5",
"RegistryKey": "Show_5_Tabs_In_Alt_Tab.reg",
"ApplyText": "> Enable showing 5 tabs from apps when snapping or pressing Alt+Tab...",
"UndoAction": null,
"RegistryUndoKey": null,
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "Show20TabsInAltTab",
"Label": "tabs from apps when snapping or pressing Alt+Tab",
"Category": "Multi-tasking",
"Action": "Show 20",
"RegistryKey": "Show_20_Tabs_In_Alt_Tab.reg",
"ApplyText": "> Enable showing 20 tabs from apps when snapping or pressing Alt+Tab...",
"UndoAction": null,
"RegistryUndoKey": null,
"MinVersion": 22000,
"MaxVersion": null
},
{
"FeatureId": "TaskbarAlignLeft",
"Label": "taskbar alignment",

View File

@@ -334,10 +334,10 @@
<!-- User TextBox Border Style with disabled state -->
<Style x:Key="UserTextBoxBorderStyle" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource ComboBgColor}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderColor}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Background" Value="{DynamicResource ComboBgColor}"/>
<Setter Property="Padding" Value="8,6"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
@@ -345,6 +345,9 @@
<Setter Property="BorderBrush" Value="{DynamicResource BorderColor}"/>
<Setter Property="Opacity" Value="0.6"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ComboHoverColor}"/>
</Trigger>
</Style.Triggers>
</Style>
@@ -694,7 +697,7 @@
<Style TargetType="Border" BasedOn="{StaticResource SearchBoxBorderStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=AppSearchBox, Path=IsFocused}" Value="True">
<Setter Property="Background" Value="{DynamicResource SecondaryButtonHover}"/>
<Setter Property="Background" Value="{DynamicResource InputFocusColor}"/>
</DataTrigger>
</Style.Triggers>
</Style>
@@ -765,7 +768,7 @@
<Style TargetType="Border" BasedOn="{StaticResource SearchBoxBorderStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TweakSearchBox, Path=IsFocused}" Value="True">
<Setter Property="Background" Value="{DynamicResource SecondaryButtonHover}"/>
<Setter Property="Background" Value="{DynamicResource InputFocusColor}"/>
</DataTrigger>
</Style.Triggers>
</Style>
@@ -857,7 +860,16 @@
</ComboBox>
<StackPanel x:Name="OtherUserPanel" Visibility="Collapsed" Margin="0,0,0,6">
<TextBlock x:Name="UsernameValidationMessage" Text="" FontStyle="Italic" Foreground="{DynamicResource CloseHover}" FontSize="11" Margin="3,0,0,4" TextWrapping="Wrap"/>
<Border Style="{StaticResource UserTextBoxBorderStyle}" IsEnabled="{Binding ElementName=OtherUsernameTextBox, Path=IsEnabled}">
<Border IsEnabled="{Binding ElementName=OtherUsernameTextBox, Path=IsEnabled}">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource UserTextBoxBorderStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=OtherUsernameTextBox, Path=IsFocused}" Value="True">
<Setter Property="Background" Value="{DynamicResource InputFocusColor}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
@@ -873,6 +885,19 @@
</StackPanel>
</Border>
<!-- App Removal Scope -->
<Border x:Name="AppRemovalScopeSection" BorderBrush="{DynamicResource BorderColor}" BorderThickness="1" CornerRadius="4" Background="{DynamicResource CardBgColor}" Padding="16,12" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="Remove Apps From" Style="{StaticResource CategoryHeaderTextBlock}"/>
<ComboBox x:Name="AppRemovalScopeCombo" Margin="0,0,0,6" AutomationProperties.Name="App Removal Scope">
<ComboBoxItem x:Name="AppRemovalScopeAllUsers" Content="All users" IsSelected="True"/>
<ComboBoxItem x:Name="AppRemovalScopeCurrentUser" Content="Current user only"/>
<ComboBoxItem x:Name="AppRemovalScopeTargetUser" Content="Target user only" Visibility="Collapsed"/>
</ComboBox>
<TextBlock x:Name="AppRemovalScopeDescription" Text="Apps will be removed for all users and from the Windows image to prevent reinstallation for new users." Foreground="{DynamicResource FgColor}" FontSize="12" TextWrapping="Wrap" Margin="0,6,0,3"/>
</StackPanel>
</Border>
<!-- Options -->
<Border BorderBrush="{DynamicResource BorderColor}" BorderThickness="1" CornerRadius="4" Background="{DynamicResource CardBgColor}" Padding="16,12,16,3" Margin="0,0,0,16">
<StackPanel>

View File

@@ -12,6 +12,7 @@ param (
[switch]$RunDefaultsLite,
[switch]$RunSavedSettings,
[string]$Apps,
[string]$AppRemovalTarget,
[switch]$RemoveApps,
[switch]$RemoveAppsCustom,
[switch]$RemoveGamingApps,
@@ -68,6 +69,10 @@ param (
[switch]$DisableDragTray,
[switch]$DisableMouseAcceleration,
[switch]$DisableStickyKeys,
[switch]$DisableWindowSnapping,
[switch]$DisableSnapAssist,
[switch]$DisableSnapLayouts,
[switch]$HideTabsInAltTab, [switch]$Show3TabsInAltTab, [switch]$Show5TabsInAltTab, [switch]$Show20TabsInAltTab,
[switch]$HideHome,
[switch]$HideGallery,
[switch]$ExplorerToHome,

View File

@@ -153,6 +153,13 @@ Below is an overview of the key features and functionality offered by Win11Deblo
- Hide the 3D objects, music or OneDrive folder from the File Explorer navigation pane. (W10 only)
- Hide the 'Include in library', 'Give access to' and 'Share' options from the context menu. (W10 only)
#### Multi-tasking
- Disable window snapping. (W11 only)
- Disable Snap Assist suggestions when snapping a window. (W11 only)
- Disable Snap Layout suggestions when dragging windows to the top of screen and when hovering on the maximize button. (W11 only)
- Change if tabs are shown when snapping or pressing Alt+Tab. (W11 only)
#### Other
- Disable Xbox Game Bar integration & game/screen recording. This also disables `ms-gamingoverlay`/`ms-gamebar` popups if you uninstall the Xbox Game Bar.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Control Panel\Desktop]
"WindowArrangementActive"="0"

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000003

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000000

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000002

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000001

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[hkey_users\default\Control Panel\Desktop]
"WindowArrangementActive"="0"

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[hkey_users\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000003

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[hkey_users\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000000

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[hkey_users\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000002

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[hkey_users\default\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"MultiTaskingAltTabFilter"=dword:00000001

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Control Panel\Desktop]
"WindowArrangementActive"="1"

View File

@@ -14,6 +14,7 @@ param (
[switch]$RunDefaultsLite,
[switch]$RunSavedSettings,
[string]$Apps,
[string]$AppRemovalTarget,
[switch]$RemoveApps,
[switch]$RemoveAppsCustom,
[switch]$RemoveGamingApps,
@@ -70,6 +71,10 @@ param (
[switch]$DisableDragTray,
[switch]$DisableMouseAcceleration,
[switch]$DisableStickyKeys,
[switch]$DisableWindowSnapping,
[switch]$DisableSnapAssist,
[switch]$DisableSnapLayouts,
[switch]$HideTabsInAltTab, [switch]$Show3TabsInAltTab, [switch]$Show5TabsInAltTab, [switch]$Show20TabsInAltTab,
[switch]$HideHome,
[switch]$HideGallery,
[switch]$ExplorerToHome,
@@ -99,7 +104,7 @@ $script:AppSelectionSchema = "$script:AssetsPath/Schemas/AppSelectionWindow.xaml
$script:MainWindowSchema = "$script:AssetsPath/Schemas/MainWindow.xaml"
$script:FeaturesFilePath = "$script:AssetsPath/Features.json"
$script:ControlParams = 'WhatIf', 'Confirm', 'Verbose', 'Debug', 'LogPath', 'Silent', 'Sysprep', 'User', 'NoRestartExplorer', 'RunDefaults', 'RunDefaultsLite', 'RunSavedSettings', 'RunAppsListGenerator', 'CLI'
$script:ControlParams = 'WhatIf', 'Confirm', 'Verbose', 'Debug', 'LogPath', 'Silent', 'Sysprep', 'User', 'NoRestartExplorer', 'RunDefaults', 'RunDefaultsLite', 'RunSavedSettings', 'RunAppsListGenerator', 'CLI', 'AppRemovalTarget'
# Script-level variables for GUI elements
$script:GuiConsoleOutput = $null
@@ -511,6 +516,7 @@ function SetWindowThemeResources {
$window.Resources.Add("SecondaryButtonPressed", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#1e1e1e")))
$window.Resources.Add("SecondaryButtonDisabled", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#3b3b3b")))
$window.Resources.Add("SecondaryButtonTextDisabled", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#787878")))
$window.Resources.Add("InputFocusColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#1f1f1f")))
$window.Resources.Add("ScrollBarThumbColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#3d3d3d")))
$window.Resources.Add("ScrollBarThumbHoverColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#4b4b4b")))
}
@@ -536,6 +542,7 @@ function SetWindowThemeResources {
$window.Resources.Add("SecondaryButtonPressed", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#f0f0f0")))
$window.Resources.Add("SecondaryButtonDisabled", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#f7f7f7")))
$window.Resources.Add("SecondaryButtonTextDisabled", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#b7b7b7")))
$window.Resources.Add("InputFocusColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#fbfbfb")))
$window.Resources.Add("ScrollBarThumbColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#b9b9b9")))
$window.Resources.Add("ScrollBarThumbHoverColor", [System.Windows.Media.SolidColorBrush]::new([System.Windows.Media.ColorConverter]::ConvertFromString("#8b8b8b")))
}
@@ -1395,6 +1402,11 @@ function OpenGUI {
$otherUsernameTextBox = $window.FindName('OtherUsernameTextBox')
$usernameTextBoxPlaceholder = $window.FindName('UsernameTextBoxPlaceholder')
$usernameValidationMessage = $window.FindName('UsernameValidationMessage')
$appRemovalScopeCombo = $window.FindName('AppRemovalScopeCombo')
$appRemovalScopeDescription = $window.FindName('AppRemovalScopeDescription')
$appRemovalScopeSection = $window.FindName('AppRemovalScopeSection')
$appRemovalScopeCurrentUser = $window.FindName('AppRemovalScopeCurrentUser')
$appRemovalScopeTargetUser = $window.FindName('AppRemovalScopeTargetUser')
# Navigation button handlers
function UpdateNavigationButtons {
@@ -1467,20 +1479,61 @@ function OpenGUI {
$userSelectionDescription.Text = "Changes will be applied to the currently logged-in user profile."
$otherUserPanel.Visibility = 'Collapsed'
$usernameValidationMessage.Text = ""
# Show "Current user only" option, hide "Target user only" option
$appRemovalScopeCurrentUser.Visibility = 'Visible'
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
# Enable app removal scope selection for current user
$appRemovalScopeCombo.IsEnabled = $true
$appRemovalScopeCombo.SelectedIndex = 0
}
1 {
$userSelectionDescription.Text = "Changes will be applied to a different user profile on this system."
$otherUserPanel.Visibility = 'Visible'
$usernameValidationMessage.Text = ""
# Hide "Current user only" option, show "Target user only" option
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
$appRemovalScopeTargetUser.Visibility = 'Visible'
# Enable app removal scope selection for other user
$appRemovalScopeCombo.IsEnabled = $true
$appRemovalScopeCombo.SelectedIndex = 0
}
2 {
$userSelectionDescription.Text = "Changes will be applied to the default user template, affecting all new users created after this point. Useful for Sysprep deployment."
$otherUserPanel.Visibility = 'Collapsed'
$usernameValidationMessage.Text = ""
# Hide other user options since they don't apply to default user template
$appRemovalScopeCurrentUser.Visibility = 'Collapsed'
$appRemovalScopeTargetUser.Visibility = 'Collapsed'
# Lock app removal scope to "All users" when applying to sysprep
$appRemovalScopeCombo.IsEnabled = $false
$appRemovalScopeCombo.SelectedIndex = 0
}
}
})
# Helper function to update app removal scope description
function UpdateAppRemovalScopeDescription {
$selectedItem = $appRemovalScopeCombo.SelectedItem
if ($selectedItem) {
switch ($selectedItem.Content) {
"All users" {
$appRemovalScopeDescription.Text = "Apps will be removed for all users and from the Windows image to prevent reinstallation for new users."
}
"Current user only" {
$appRemovalScopeDescription.Text = "Apps will only be removed for the current user. Other users and new users will not be affected."
}
"Target user only" {
$appRemovalScopeDescription.Text = "Apps will only be removed for the specified target user. Other users and new users will not be affected."
}
}
}
}
# Update app removal scope description
$appRemovalScopeCombo.Add_SelectionChanged({
UpdateAppRemovalScopeDescription
})
$otherUsernameTextBox.Add_TextChanged({
# Show/hide placeholder
if ([string]::IsNullOrWhiteSpace($otherUsernameTextBox.Text)) {
@@ -1547,6 +1600,22 @@ function OpenGUI {
$changesList += "Remove $selectedAppsCount selected application(s)"
}
# Update app removal scope section based on whether apps are selected
if ($selectedAppsCount -gt 0) {
# Enable app removal scope selection (unless locked by sysprep mode)
if ($userSelectionCombo.SelectedIndex -ne 2) {
$appRemovalScopeCombo.IsEnabled = $true
}
$appRemovalScopeSection.Opacity = 1.0
UpdateAppRemovalScopeDescription
}
else {
# Disable app removal scope selection when no apps selected
$appRemovalScopeCombo.IsEnabled = $false
$appRemovalScopeSection.Opacity = 0.5
$appRemovalScopeDescription.Text = "No apps selected for removal."
}
# Collect all ComboBox/CheckBox selections from dynamically created controls
if ($script:UiControlMappings) {
foreach ($mappingKey in $script:UiControlMappings.Keys) {
@@ -1626,13 +1695,6 @@ function OpenGUI {
return
}
$controlParamsCount = 0
foreach ($Param in $script:ControlParams) {
if ($script:Params.ContainsKey($Param)) {
$controlParamsCount++
}
}
# App Removal - collect selected apps from integrated UI
$selectedApps = @()
foreach ($child in $appsPanel.Children) {
@@ -1658,6 +1720,23 @@ function OpenGUI {
AddParameter 'RemoveApps'
AddParameter 'Apps' ($selectedApps -join ',')
# Add app removal target parameter based on selection
$selectedScopeItem = $appRemovalScopeCombo.SelectedItem
if ($selectedScopeItem) {
switch ($selectedScopeItem.Content) {
"All users" {
AddParameter 'AppRemovalTarget' 'AllUsers'
}
"Current user only" {
AddParameter 'AppRemovalTarget' 'CurrentUser'
}
"Target user only" {
# Use the target username from Other User panel
AddParameter 'AppRemovalTarget' ($otherUsernameTextBox.Text.Trim())
}
}
}
}
# Apply dynamic tweaks selections
@@ -1694,12 +1773,19 @@ function OpenGUI {
}
}
$controlParamsCount = 0
foreach ($Param in $script:ControlParams) {
if ($script:Params.ContainsKey($Param)) {
$controlParamsCount++
}
}
# Check if any changes were selected
$totalChanges = $script:Params.Count - $controlParamsCount
# Apps parameter does not count as a change itself
if ($script:Params.ContainsKey('Apps')) {
$totalChanges--
$totalChanges = $totalChanges - 1
}
if ($totalChanges -eq 0) {
@@ -2214,12 +2300,37 @@ function GetInstalledAppsViaWinget {
}
# Removes apps specified during function call from all user accounts and from the OS image.
# Target is determined from $script:Params["AppRemovalTarget"] or defaults to "AllUsers"
# Target values: "AllUsers" (removes for all users + from image), "CurrentUser", or a specific username
function GetTargetUserForAppRemoval {
if ($script:Params.ContainsKey("AppRemovalTarget")) {
return $script:Params["AppRemovalTarget"]
}
return "AllUsers"
}
function GetFriendlyTargetUserName {
$target = GetTargetUserForAppRemoval
switch ($target) {
"AllUsers" { return "all users" }
"CurrentUser" { return "the current user" }
default { return "user $target" }
}
}
# Removes apps specified during function call based on the target scope.
function RemoveApps {
param (
$appslist
)
# Determine target from script-level params, defaulting to AllUsers
$targetUser = GetTargetUserForAppRemoval
Foreach ($app in $appsList) {
if ($script:CancelRequested) {
return
@@ -2274,31 +2385,38 @@ function RemoveApps {
}
# Use Remove-AppxPackage to remove all other apps
$app = '*' + $app + '*'
$appPattern = '*' + $app + '*'
# Remove installed app for all existing users
try {
Get-AppxPackage -Name $app -AllUsers | Remove-AppxPackage -AllUsers -ErrorAction Continue
switch ($targetUser) {
"AllUsers" {
# Remove installed app for all existing users
Get-AppxPackage -Name $appPattern -AllUsers | Remove-AppxPackage -AllUsers -ErrorAction Continue
if ($DebugPreference -ne "SilentlyContinue") {
Write-ToConsole "Removed $app for all users" -ForegroundColor DarkGray
# Remove provisioned app from OS image, so the app won't be installed for any new users
Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like $appPattern } | ForEach-Object { Remove-ProvisionedAppxPackage -Online -AllUsers -PackageName $_.PackageName }
}
"CurrentUser" {
# Remove installed app for current user only
Get-AppxPackage -Name $appPattern | Remove-AppxPackage -ErrorAction Continue
}
default {
# Target is a specific username - remove app for that user only
# Get the user's SID
$userAccount = New-Object System.Security.Principal.NTAccount($targetUser)
$userSid = $userAccount.Translate([System.Security.Principal.SecurityIdentifier]).Value
# Remove the app package for the specific user
Get-AppxPackage -Name $appPattern -User $userSid | Remove-AppxPackage -User $userSid -ErrorAction Continue
}
}
}
catch {
if ($DebugPreference -ne "SilentlyContinue") {
Write-ToConsole "Unable to remove $app for all users" -ForegroundColor Yellow
Write-ToConsole "Something went wrong while trying to remove $app" -ForegroundColor Yellow
Write-Host $psitem.Exception.StackTrace -ForegroundColor Gray
}
}
# Remove provisioned app from OS image, so the app won't be installed for any new users
try {
Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like $app } | ForEach-Object { Remove-ProvisionedAppxPackage -Online -AllUsers -PackageName $_.PackageName }
}
catch {
Write-ToConsole "Unable to remove $app from windows image" -ForegroundColor Yellow
Write-Host $psitem.Exception.StackTrace -ForegroundColor Gray
}
}
Write-ToConsole ""
@@ -2520,7 +2638,6 @@ function RegImport {
reg load "HKU\Default" $userPath | Out-Null
$regOutput = reg import "$script:RegfilesPath\Sysprep\$path" 2>&1
reg unload "HKU\Default" | Out-Null
}
else {
$regOutput = reg import "$script:RegfilesPath\$path" 2>&1
@@ -2886,7 +3003,7 @@ function ExecuteParameter {
# Handle features without RegistryKey or with special logic
switch ($paramKey) {
'RemoveApps' {
Write-ToConsole "> Removing selected apps..."
Write-ToConsole "> Removing selected apps for $(GetFriendlyTargetUserName)..."
$appsList = GenerateAppsList
if ($appsList.Count -eq 0) {
@@ -3295,10 +3412,13 @@ if ($script:Params.ContainsKey("Sysprep")) {
}
}
# Make sure all requirements for User mode are met, if User is specified
# Ensure that target user exists, if User or AppRemovalTarget parameter was provided
if ($script:Params.ContainsKey("User")) {
$userPath = GetUserDirectory -userName $script:Params.Item("User")
}
if ($script:Params.ContainsKey("AppRemovalTarget")) {
$userPath = GetUserDirectory -userName $script:Params.Item("AppRemovalTarget")
}
# Remove LastUsedSettings.json file if it exists and is empty
if ((Test-Path $script:SavedSettingsFilePath) -and ([String]::IsNullOrWhiteSpace((Get-content $script:SavedSettingsFilePath)))) {