mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-07-03 07:08:27 +00:00
Compare commits
3 Commits
master
...
allow-mult
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a8999f635 | ||
|
|
5bd8c9957b | ||
|
|
88b5f1b629 |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -18,7 +18,7 @@ You can help us test the latest changes and additions to the script. If you enco
|
||||
You can launch the prerelease version of Win11Debloat by running this command:
|
||||
|
||||
```ps1
|
||||
& ([scriptblock]::Create((irm "https://debloat.raphi.re/"))) -Dev
|
||||
& ([scriptblock]::Create((irm "https://debloat.raphi.re/dev")))
|
||||
```
|
||||
|
||||
# Contributing Code
|
||||
|
||||
62
README.md
62
README.md
@@ -6,7 +6,7 @@
|
||||
|
||||
Win11Debloat is a lightweight, easy to use PowerShell script that allows you to quickly declutter and customize your Windows experience, no installation required! You can use it to remove pre-installed apps, disable telemetry, remove intrusive interface elements and much more. No need to painstakingly go through all the settings yourself or remove apps one by one. Win11Debloat makes the process quick and easy!
|
||||
|
||||
The script also includes many features that system administrators and power users will enjoy. Such as a powerful command-line interface, support for Windows Audit mode and the ability to make changes to other Windows users. You can also easily export & import your preferred settings, allowing you to quickly apply the same settings on all your systems. Please refer to our [wiki](https://github.com/Raphire/Win11Debloat/wiki) for more details.
|
||||
The script also includes many features that system administrators and power users will enjoy. Such as a powerful command-line interface, support for Windows Audit mode and the ability to make changes to other Windows users. Please refer to our [wiki](https://github.com/Raphire/Win11Debloat/wiki/) for more details.
|
||||
|
||||

|
||||
|
||||
@@ -23,14 +23,14 @@ The script also includes many features that system administrators and power user
|
||||
|
||||
Download & run the script automatically via PowerShell.
|
||||
|
||||
1. Open PowerShell or Terminal.
|
||||
1. Open PowerShell or Terminal, preferably as an administrator.
|
||||
2. Copy and paste the command below into PowerShell:
|
||||
|
||||
```PowerShell
|
||||
& ([scriptblock]::Create((irm "https://debloat.raphi.re/")))
|
||||
```
|
||||
|
||||
3. Wait for the script to automatically download and launch Win11Debloat.
|
||||
3. Wait for the script to automatically download Win11Debloat.
|
||||
4. Carefully read through and follow the on-screen instructions.
|
||||
|
||||
This method supports command-line parameters to customize the behaviour of the script. Please click [here](https://github.com/Raphire/Win11Debloat/wiki/Command%E2%80%90line-Interface#parameters) for more information.
|
||||
@@ -74,10 +74,10 @@ This method supports command-line parameters to customize the behaviour of the s
|
||||
|
||||
## Features
|
||||
|
||||
Below is an overview of the key features and functionality offered by Win11Debloat. You can visit the [the wiki](https://github.com/Raphire/Win11Debloat/wiki) for more details.
|
||||
Below is an overview of the key features and functionality offered by Win11Debloat. Please refer to [the wiki](https://github.com/Raphire/Win11Debloat/wiki/Default-Settings) for more information about the default settings preset.
|
||||
|
||||
> [!Tip]
|
||||
> All of the changes made by Win11Debloat can easily be reverted and almost all of the apps can be reinstalled through the Microsoft Store. You can visit [the wiki](https://github.com/Raphire/Win11Debloat/wiki/Reverting-Changes) for more information on reverting changes.
|
||||
> All of the changes made by Win11Debloat can easily be reverted and almost all of the apps can be reinstalled through the Microsoft Store. A full guide on how to revert changes can be found [here](https://github.com/Raphire/Win11Debloat/wiki/Reverting-Changes).
|
||||
|
||||
#### App Removal
|
||||
|
||||
@@ -86,15 +86,23 @@ Below is an overview of the key features and functionality offered by Win11Deblo
|
||||
#### Privacy & Suggested Content
|
||||
|
||||
- Disable telemetry, diagnostic data, activity history, app-launch tracking & targeted ads.
|
||||
- Disable tips, tricks, suggestions & ads across Windows, the lock screen and Microsoft Edge.
|
||||
- Disable Windows location services, app location access and Find My Device location tracking.
|
||||
- Disable tips, tricks, suggestions & ads across Windows.
|
||||
- Disable Windows location services & app location access.
|
||||
- Disable Find My Device location tracking.
|
||||
- Disable 'Windows Spotlight' and tips & tricks on the lock screen.
|
||||
- Disable 'Windows Spotlight' desktop background option.
|
||||
- Disable ads, suggestions and the MSN news feed in Microsoft Edge.
|
||||
- Hide Microsoft 365 ads on the Settings 'Home' page, or hide the 'Home' page entirely.
|
||||
|
||||
#### AI Features
|
||||
|
||||
- Disable & remove Microsoft Copilot, Windows Recall and Click to Do.
|
||||
- Disable & remove Microsoft Copilot.
|
||||
- Disable Windows Recall.
|
||||
- Disable Click to Do, AI text & image analysis tool.
|
||||
- Prevent AI service (WSAIFabricSvc) from starting automatically.
|
||||
- Disable AI Features in Edge, Paint and Notepad.
|
||||
- Disable AI Features in Edge.
|
||||
- Disable AI Features in Paint.
|
||||
- Disable AI Features in Notepad.
|
||||
|
||||
#### System
|
||||
|
||||
@@ -116,38 +124,50 @@ Below is an overview of the key features and functionality offered by Win11Deblo
|
||||
#### Appearance
|
||||
|
||||
- Enable dark mode for system and apps.
|
||||
- Disable transparency, animations and visual effects.
|
||||
- Disable transparency effects
|
||||
- Disable animations and visual effects.
|
||||
|
||||
#### Start Menu & Search
|
||||
|
||||
- Customize the start menu by removing pinned apps, hiding recommendations, and customizing the 'All Apps' section.
|
||||
- Remove or replace all pinned apps from the start menu.
|
||||
- Hide the recommended section in the start menu.
|
||||
- Hide the 'All Apps' section in the start menu.
|
||||
- Disable the Phone Link mobile devices integration in the start menu.
|
||||
- Disable Bing web search & Copilot integration and Microsoft Store app suggestions in Windows search.
|
||||
- Disable Bing web search & Copilot integration in Windows search.
|
||||
- Disable Microsoft Store app suggestions in Windows search.
|
||||
- Disable Search Highlights (dynamic/branded content) in the taskbar search box.
|
||||
- Disable local Windows search history.
|
||||
|
||||
#### Taskbar
|
||||
|
||||
- Change taskbar alignment.
|
||||
- Customize or hide taskbar buttons like the search bar, taskview and more.
|
||||
- Align taskbar icons to the left.
|
||||
- Hide or change the search icon/box on the taskbar.
|
||||
- Hide the taskview button from the taskbar.
|
||||
- Disable widgets on the taskbar & lock screen.
|
||||
- Enable the 'End Task' option in the taskbar right click menu to quickly force-close apps.
|
||||
- Hide the chat (meet now) icon from the taskbar.
|
||||
- Enable the 'End Task' option in the taskbar right click menu.
|
||||
- Enable the 'Last Active Click' behavior in the taskbar app area. This allows you to repeatedly click on an application's icon in the taskbar to switch focus between the open windows of that application.
|
||||
- Customize how app buttons are shown on the taskbar.
|
||||
- Choose how app icons are shown on the taskbar when using multiple monitors.
|
||||
- Choose combine mode for taskbar buttons and labels.
|
||||
|
||||
#### File Explorer
|
||||
|
||||
- Change the default location that File Explorer opens to.
|
||||
- Show file extensions for known file types.
|
||||
- Show hidden files, folders and drives.
|
||||
- Hide the Home, Gallery or OneDrive section from the File Explorer navigation pane.
|
||||
- Hide the Home or Gallery section from the File Explorer navigation pane.
|
||||
- Hide duplicate removable drive entries from the File Explorer navigation pane, so only the entry under 'This PC' remains.
|
||||
- Add all common folders (Desktop, Downloads, etc.) back to 'This PC' in File Explorer.
|
||||
- Hide the 3D objects, music or OneDrive folder from the File Explorer navigation pane.
|
||||
- Hide the 'Include in library', 'Give access to' and 'Share' options from the context menu.
|
||||
- Change drive letter position or visibility in File Explorer.
|
||||
|
||||
#### Multi-tasking
|
||||
|
||||
- Disable window snapping.
|
||||
- Disable Snap Assist and Snap Layout suggestions when dragging or snapping windows.
|
||||
- Change whether tabs are shown when snapping windows or pressing Alt+Tab.
|
||||
- Disable Snap Assist suggestions when snapping a window.
|
||||
- Disable Snap Layout suggestions when dragging windows to the top of screen and when hovering on the maximize button.
|
||||
- Change if tabs are shown when snapping or pressing Alt+Tab.
|
||||
|
||||
#### Optional Windows Features
|
||||
|
||||
@@ -161,12 +181,12 @@ Below is an overview of the key features and functionality offered by Win11Deblo
|
||||
|
||||
#### Advanced Features
|
||||
|
||||
- Ability to [apply changes to a different user](https://github.com/Raphire/Win11Debloat/wiki/Advanced-Features#running-as-another-user), instead of the currently logged in user.
|
||||
- Option to [apply changes to a different user](https://github.com/Raphire/Win11Debloat/wiki/Advanced-Features#running-as-another-user), instead of the currently logged in user.
|
||||
- [Sysprep mode](https://github.com/Raphire/Win11Debloat/wiki/Advanced-Features#sysprep-mode) to apply changes to the Windows Default user profile. Which ensures, all new users will have the changes automatically applied to them.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions of all kinds! Please see our [Contributing Guidelines](https://github.com/Raphire/Win11Debloat/blob/master/.github/CONTRIBUTING.md) for detailed instructions on how to get started and best practices for contributing.
|
||||
We welcome contributions of all kinds! Please see our [Contributing Guidelines](/.github/CONTRIBUTING.md) for detailed instructions on how to get started and best practices for contributing.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
4
Run.bat
4
Run.bat
@@ -4,10 +4,10 @@ setlocal EnableDelayedExpansion
|
||||
:: Set Windows Terminal installation paths. (Default and Scoop installation)
|
||||
set "wtDefaultPath=%LOCALAPPDATA%\Microsoft\WindowsApps\wt.exe"
|
||||
set "wtScoopPath=%USERPROFILE%\scoop\apps\windows-terminal\current\wt.exe"
|
||||
set "logFile=%~dp0Logs\Win11Debloat-Run.log"
|
||||
set "logFile=%LOCALAPPDATA%\Win11Debloat\Logs\Win11Debloat-Run.log"
|
||||
|
||||
:: Ensure Logs folder exists
|
||||
if not exist "%~dp0Logs" mkdir "%~dp0Logs"
|
||||
if not exist "%LOCALAPPDATA%\Win11Debloat\Logs" mkdir "%LOCALAPPDATA%\Win11Debloat\Logs"
|
||||
|
||||
:: Determine which terminal exists
|
||||
if exist "%wtDefaultPath%" (
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
|
||||
Title="Win11Debloat"
|
||||
MinWidth="860" MinHeight="640"
|
||||
MinWidth="860" MinHeight="600"
|
||||
ResizeMode="CanResize"
|
||||
SnapsToDevicePixels="True"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="False"
|
||||
Background="{DynamicResource AppBorderColor}"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
Foreground="{DynamicResource AppFgColor}">
|
||||
<shell:WindowChrome.WindowChrome>
|
||||
<shell:WindowChrome ResizeBorderThickness="5"
|
||||
@@ -464,7 +464,7 @@
|
||||
<Grid>
|
||||
<StackPanel x:Name="HomeContentPanel" HorizontalAlignment="Center" VerticalAlignment="Top">
|
||||
<!-- Logo -->
|
||||
<Viewbox Width="250" Height="250" Margin="0,0,0,16" HorizontalAlignment="Center">
|
||||
<Viewbox Width="250" Height="250" Margin="0,0,0,24" HorizontalAlignment="Center">
|
||||
<Grid Width="250" Height="250">
|
||||
<!-- Windows logo style icon -->
|
||||
<Path x:Name="LogoFallback" Data="M0,0 L80,0 L80,80 L0,80 Z M90,0 L170,0 L170,80 L90,80 Z M0,90 L80,90 L80,170 L0,170 Z M90,90 L170,90 L170,170 L90,170 Z"
|
||||
@@ -483,7 +483,7 @@
|
||||
|
||||
<!-- Title -->
|
||||
<TextBlock Text="Welcome to Win11Debloat" FontSize="40" FontWeight="SemiBold" Foreground="{DynamicResource AppFgColor}" HorizontalAlignment="Center"/>
|
||||
<TextBlock TextWrapping="Wrap" Foreground="{DynamicResource AppFgColor}" FontSize="20" HorizontalAlignment="Center" Margin="0,4,0,48">
|
||||
<TextBlock TextWrapping="Wrap" Foreground="{DynamicResource AppFgColor}" FontSize="20" HorizontalAlignment="Center" Margin="0,8,0,64">
|
||||
<Run Text="Your clean Windows experience is just a few clicks away!"/>
|
||||
</TextBlock>
|
||||
|
||||
|
||||
@@ -113,15 +113,16 @@ function ReplaceStartMenu {
|
||||
return
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
|
||||
$backupFileName = "Win11Debloat-StartBackup-$timestamp.bak"
|
||||
$startMenuDir = Split-Path $startMenuBinFile -Parent
|
||||
$backupBinFile = Join-Path $startMenuDir $backupFileName
|
||||
$startMenuBackupsDir = Join-Path $script:AppDataPath 'Backups'
|
||||
if (-not (Test-Path $startMenuBackupsDir)) {
|
||||
New-Item -ItemType Directory -Path $startMenuBackupsDir -Force | Out-Null
|
||||
}
|
||||
$backupTimestamp = (Get-Date).ToString('yyyyMMdd_HHmmss')
|
||||
$backupBinFile = Join-Path $startMenuBackupsDir "Win11Debloat-Start2BinBackup-$userName-$backupTimestamp.bak"
|
||||
|
||||
if (Test-Path $startMenuBinFile) {
|
||||
# Backup current start menu file
|
||||
Copy-Item -Path $startMenuBinFile -Destination $backupBinFile -Force
|
||||
Write-Verbose "Start menu backup for user $userName saved to $backupFileName"
|
||||
Move-Item -Path $startMenuBinFile -Destination $backupBinFile -Force
|
||||
}
|
||||
else {
|
||||
Write-Host "Unable to find original start2.bin file for user $userName, no backup was created for this user" -ForegroundColor Yellow
|
||||
@@ -193,55 +194,6 @@ function GetStartMenuUserNameFromPath {
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the path to the latest start menu backup file for the given scope.
|
||||
|
||||
.DESCRIPTION
|
||||
Resolves the LocalState folder for the specified scope and returns the
|
||||
full path to the most recent Win11Debloat-StartBackup-*.bak file, or
|
||||
$null if no backup exists.
|
||||
|
||||
For CurrentUser, uses $env:LOCALAPPDATA directly. For AllUsers, scans
|
||||
every user profile.
|
||||
|
||||
.PARAMETER Scope
|
||||
The scope to check: CurrentUser or AllUsers.
|
||||
|
||||
.EXAMPLE
|
||||
$backupPath = Get-StartMenuBackupPath -Scope 'CurrentUser'
|
||||
|
||||
.EXAMPLE
|
||||
$backupPath = Get-StartMenuBackupPath -Scope 'AllUsers'
|
||||
#>
|
||||
function Get-StartMenuBackupPath {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet('CurrentUser', 'AllUsers')]
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
if ($Scope -eq 'CurrentUser') {
|
||||
$localStateDir = "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState"
|
||||
$latestBackup = Get-ChildItem -Path (Join-Path $localStateDir 'Win11Debloat-StartBackup-*.bak') -ErrorAction SilentlyContinue |
|
||||
Sort-Object Name -Descending |
|
||||
Select-Object -First 1
|
||||
if ($latestBackup) { return $latestBackup.FullName }
|
||||
return $null
|
||||
}
|
||||
else {
|
||||
$userPathString = GetUserDirectory -userName "*" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState"
|
||||
$usersStartMenuPaths = Get-ChildItem -Path $userPathString -ErrorAction SilentlyContinue
|
||||
foreach ($startMenuPath in $usersStartMenuPaths) {
|
||||
$latestBackup = Get-ChildItem -Path (Join-Path $startMenuPath.FullName 'Win11Debloat-StartBackup-*.bak') -ErrorAction SilentlyContinue |
|
||||
Sort-Object Name -Descending |
|
||||
Select-Object -First 1
|
||||
if ($latestBackup) { return $latestBackup.FullName }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
@@ -257,14 +209,14 @@ function Get-StartMenuBackupPath {
|
||||
The full path to the user's start2.bin file to restore.
|
||||
|
||||
.PARAMETER BackupFilePath
|
||||
Path to the backup file to restore from. If omitted, automatically
|
||||
finds the latest Win11Debloat-StartBackup-*.bak file.
|
||||
Path to the backup file to restore from. If omitted, defaults to
|
||||
StartMenuBinFile with a .bak extension.
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenuFromBackup -StartMenuBinFile "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin"
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenuFromBackup -StartMenuBinFile "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin" -BackupFilePath "C:\Backups\Win11Debloat-StartBackup-20260101_120000.bak"
|
||||
RestoreStartMenuFromBackup -StartMenuBinFile "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin" -BackupFilePath "C:\Backups\start2.bin"
|
||||
#>
|
||||
function RestoreStartMenuFromBackup {
|
||||
param(
|
||||
@@ -274,32 +226,20 @@ function RestoreStartMenuFromBackup {
|
||||
)
|
||||
|
||||
$userName = GetStartMenuUserNameFromPath -StartMenuBinFile $StartMenuBinFile
|
||||
$backupBinFile = if ([string]::IsNullOrWhiteSpace($BackupFilePath)) {
|
||||
# Auto-detect latest backup in the same folder as the start2.bin
|
||||
$startMenuDir = Split-Path $StartMenuBinFile -Parent
|
||||
$latestBackup = Get-ChildItem -Path (Join-Path $startMenuDir 'Win11Debloat-StartBackup-*.bak') -ErrorAction SilentlyContinue |
|
||||
Sort-Object Name -Descending |
|
||||
Select-Object -First 1
|
||||
$backupTimestamp = (Get-Date).ToString('yyyyMMdd_HHmmss')
|
||||
$startMenuBackupsDir = Join-Path $script:AppDataPath 'Backups'
|
||||
if (-not (Test-Path $startMenuBackupsDir)) { New-Item -ItemType Directory -Path $startMenuBackupsDir -Force | Out-Null }
|
||||
|
||||
if ($latestBackup) { $latestBackup.FullName } else { $null }
|
||||
$resolvedBackupPath = if ([string]::IsNullOrWhiteSpace($BackupFilePath)) {
|
||||
Join-Path $startMenuBackupsDir "Win11Debloat-Start2BinBackup-$userName-$backupTimestamp.bak"
|
||||
}
|
||||
else {
|
||||
$BackupFilePath
|
||||
}
|
||||
$restoreTimestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
|
||||
$restoreBackupFileName = "Win11Debloat-StartRestore-$restoreTimestamp.bak"
|
||||
$currentBinBackup = Join-Path (Split-Path $StartMenuBinFile -Parent) $restoreBackupFileName
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($backupBinFile)) {
|
||||
return [PSCustomObject]@{
|
||||
UserName = $userName
|
||||
Result = $false
|
||||
Message = "No start menu backup file found for user $userName."
|
||||
}
|
||||
}
|
||||
$currentBinBackup = Join-Path $startMenuBackupsDir "Win11Debloat-Start2BinRestore-$userName-$backupTimestamp.bak"
|
||||
|
||||
if ($script:Params.ContainsKey("WhatIf")) {
|
||||
Write-Host "[WhatIf] Restore start menu for user $userName from backup $backupBinFile" -ForegroundColor Cyan
|
||||
Write-Host "[WhatIf] Restore start menu for user $userName from backup $resolvedBackupPath" -ForegroundColor Cyan
|
||||
return [PSCustomObject]@{
|
||||
UserName = $userName
|
||||
Result = $true
|
||||
@@ -307,11 +247,11 @@ function RestoreStartMenuFromBackup {
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $backupBinFile)) {
|
||||
if (-not (Test-Path -LiteralPath $resolvedBackupPath)) {
|
||||
return [PSCustomObject]@{
|
||||
UserName = $userName
|
||||
Result = $false
|
||||
Message = "No start menu backup file found for user $userName."
|
||||
Message = "Start menu backup file not found: $resolvedBackupPath"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +260,7 @@ function RestoreStartMenuFromBackup {
|
||||
Move-Item -Path $StartMenuBinFile -Destination $currentBinBackup -Force
|
||||
}
|
||||
|
||||
Copy-Item -Path $backupBinFile -Destination $StartMenuBinFile -Force
|
||||
Copy-Item -Path $resolvedBackupPath -Destination $StartMenuBinFile -Force
|
||||
return [PSCustomObject]@{
|
||||
UserName = $userName
|
||||
Result = $true
|
||||
@@ -341,26 +281,34 @@ function RestoreStartMenuFromBackup {
|
||||
Restores the start menu for the current target user from a backup.
|
||||
|
||||
.DESCRIPTION
|
||||
Resolves the start2.bin path for the currently logged-in user, then
|
||||
delegates to RestoreStartMenuFromBackup.
|
||||
Resolves the start2.bin path for the current user (or the user specified
|
||||
via the -User parameter), then delegates to RestoreStartMenuFromBackup.
|
||||
Returns early with a warning if the user's start menu path cannot
|
||||
be resolved.
|
||||
|
||||
.PARAMETER BackupFilePath
|
||||
Path to the backup file to restore from. If omitted, automatically
|
||||
finds the latest Win11Debloat-StartBackup-*.bak file.
|
||||
Path to the backup file to restore from.
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenu
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenu -BackupFilePath "C:\Backups\Win11Debloat-StartBackup-20260101_120000.bak"
|
||||
RestoreStartMenu -BackupFilePath "$env:LOCALAPPDATA\Win11Debloat\Backups\Win11Debloat-Start2BinBackup-Jeff-20260623_143000.bak"
|
||||
#>
|
||||
function RestoreStartMenu {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$BackupFilePath
|
||||
)
|
||||
|
||||
$targetUserName = $env:USERNAME
|
||||
$startMenuBinFile = "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin"
|
||||
$targetUserName = GetUserName
|
||||
$startMenuBinFile = GetStartMenuBinPathForUser -UserName $targetUserName
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($startMenuBinFile)) {
|
||||
Write-Host "Unable to resolve start menu path for user $targetUserName, nothing to restore" -ForegroundColor Yellow
|
||||
return [PSCustomObject]@{
|
||||
UserName = $targetUserName
|
||||
Result = $false
|
||||
Message = "Could not resolve start menu path for user $targetUserName."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Restoring start menu for user $targetUserName from backup..."
|
||||
|
||||
@@ -373,24 +321,19 @@ function RestoreStartMenu {
|
||||
|
||||
.DESCRIPTION
|
||||
Iterates over every existing user profile and restores each user's
|
||||
start2.bin from the latest backup in their LocalState folder. For the
|
||||
Default user profile, removes the start2.bin file (which was previously
|
||||
copied from a template) so that new profiles revert to the system
|
||||
default start menu.
|
||||
start2.bin from the specified backup file. For the Default user profile,
|
||||
removes the start2.bin file (which was previously copied from a template)
|
||||
so that new profiles revert to the system default start menu.
|
||||
|
||||
.PARAMETER BackupFilePath
|
||||
Path to the backup file to restore from. If omitted, automatically
|
||||
finds the latest Win11Debloat-StartBackup-*.bak in each user's
|
||||
LocalState folder.
|
||||
Path to the backup file to restore from.
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenuForAllUsers
|
||||
|
||||
.EXAMPLE
|
||||
RestoreStartMenuForAllUsers -BackupFilePath "C:\Backups\Win11Debloat-StartBackup-20260101_120000.bak"
|
||||
RestoreStartMenuForAllUsers -BackupFilePath "$env:LOCALAPPDATA\Win11Debloat\Backups\Win11Debloat-Start2BinBackup-Jeff-20260623_143000.bak"
|
||||
#>
|
||||
function RestoreStartMenuForAllUsers {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$BackupFilePath
|
||||
)
|
||||
|
||||
|
||||
@@ -1,19 +1,3 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Loads a registry backup from a JSON file and normalizes its contents.
|
||||
|
||||
.DESCRIPTION
|
||||
Loads a registry backup from disk and returns a normalized representation
|
||||
of its contents suitable for use by the restore workflow. Throws if the
|
||||
file is missing, unreadable, or not valid JSON.
|
||||
|
||||
.PARAMETER FilePath
|
||||
The absolute path to the registry backup JSON file to load.
|
||||
|
||||
.OUTPUTS
|
||||
PSCustomObject
|
||||
A normalized registry backup object produced by Normalize-RegistryBackup.
|
||||
#>
|
||||
function Load-RegistryBackupFromFile {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -34,24 +18,6 @@ function Load-RegistryBackupFromFile {
|
||||
return Normalize-RegistryBackup -Backup $rawBackup
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Validates and normalizes a raw registry backup object.
|
||||
|
||||
.DESCRIPTION
|
||||
Validates the structure and content of the supplied backup and converts
|
||||
it into a normalized representation that can be safely consumed by the
|
||||
restore workflow. Throws if validation fails.
|
||||
|
||||
.PARAMETER Backup
|
||||
The raw backup object (typically parsed from JSON) to normalize.
|
||||
|
||||
.OUTPUTS
|
||||
PSCustomObject
|
||||
A normalized backup with Version, BackupType, CreatedAt, CreatedBy,
|
||||
ComputerName, Target, SelectedFeatures, SelectedUndoFeatures, and
|
||||
RegistryKeys properties.
|
||||
#>
|
||||
function Normalize-RegistryBackup {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -131,16 +97,9 @@ function Normalize-RegistryBackup {
|
||||
if ($allSelectedFeatures.Count -eq 0) {
|
||||
$errors.Add('Backup must contain at least one feature ID in SelectedFeatures or SelectedUndoFeatures.')
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$allowListValidationErrors = @(Test-RegistryBackupMatchesSelectedFeatures -SelectedFeatureIds @($selectedFeatures) -SelectedUndoFeatureIds @($selectedUndoFeatures) -Target $normalizedTarget -RegistryKeys @($normalizedKeys))
|
||||
foreach ($allowListValidationError in $allowListValidationErrors) {
|
||||
$errors.Add([string]$allowListValidationError)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errors.Add("Failed to validate backup: $($_.Exception.Message)")
|
||||
}
|
||||
$allowListValidationErrors = @(Test-RegistryBackupMatchesSelectedFeatures -SelectedFeatureIds @($selectedFeatures) -SelectedUndoFeatureIds @($selectedUndoFeatures) -Target $normalizedTarget -RegistryKeys @($normalizedKeys))
|
||||
foreach ($allowListValidationError in $allowListValidationErrors) {
|
||||
$errors.Add([string]$allowListValidationError)
|
||||
}
|
||||
|
||||
if ($errors.Count -gt 0) {
|
||||
@@ -166,23 +125,6 @@ function Normalize-RegistryBackup {
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Restores registry state from a normalized backup object.
|
||||
|
||||
.DESCRIPTION
|
||||
Applies the registry state described by the supplied backup back to the
|
||||
registry, loading the appropriate user hive when required.
|
||||
|
||||
.PARAMETER Backup
|
||||
A normalized backup object (as produced by Normalize-RegistryBackup) whose
|
||||
RegistryKeys snapshots should be restored.
|
||||
|
||||
.OUTPUTS
|
||||
PSCustomObject
|
||||
Returns an object with a Result property set to $true when the restore
|
||||
completes successfully.
|
||||
#>
|
||||
function Restore-RegistryBackupState {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
|
||||
@@ -1,5 +1,71 @@
|
||||
# MainWindow-WindowChrome.ps1
|
||||
# Window sizing, DPI-aware coordinate conversion, and UI animations.
|
||||
# Window sizing, DPI-aware coordinate conversion, maximized-window taskbar-constraint helpers, and UI animations.
|
||||
|
||||
function Register-MaximizedWindowHelper {
|
||||
if (-not ([System.Management.Automation.PSTypeName]'Win11Debloat.MaximizedWindowHelper').Type) {
|
||||
Add-Type -Namespace Win11Debloat -Name MaximizedWindowHelper `
|
||||
-ReferencedAssemblies 'PresentationFramework','System.Windows.Forms','System.Drawing' `
|
||||
-MemberDefinition @'
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct MINMAXINFO {
|
||||
public POINT ptReserved, ptMaxSize, ptMaxPosition, ptMinTrackSize, ptMaxTrackSize;
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct POINT { public int x, y; }
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
||||
private static extern System.IntPtr MonitorFromWindow(System.IntPtr hwnd, uint dwFlags);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
||||
private static extern bool GetMonitorInfo(System.IntPtr hMonitor, ref MONITORINFO lpmi);
|
||||
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct RECT {
|
||||
public int Left, Top, Right, Bottom;
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
||||
private struct MONITORINFO {
|
||||
public int cbSize;
|
||||
public RECT rcMonitor;
|
||||
public RECT rcWork;
|
||||
public uint dwFlags;
|
||||
}
|
||||
|
||||
public static System.IntPtr WmGetMinMaxInfoHook(
|
||||
System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) {
|
||||
if (msg == 0x0024) { // WM_GETMINMAXINFO
|
||||
var mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(
|
||||
lParam, typeof(MINMAXINFO));
|
||||
|
||||
const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
|
||||
var monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
var monitorInfo = new MONITORINFO();
|
||||
monitorInfo.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MONITORINFO));
|
||||
|
||||
if (monitor != System.IntPtr.Zero && GetMonitorInfo(monitor, ref monitorInfo)) {
|
||||
mmi.ptMaxPosition.x = monitorInfo.rcWork.Left - monitorInfo.rcMonitor.Left;
|
||||
mmi.ptMaxPosition.y = monitorInfo.rcWork.Top - monitorInfo.rcMonitor.Top;
|
||||
mmi.ptMaxSize.x = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
|
||||
mmi.ptMaxSize.y = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;
|
||||
}
|
||||
else {
|
||||
var screen = System.Windows.Forms.Screen.FromHandle(hwnd);
|
||||
var wa = screen.WorkingArea;
|
||||
var bounds = screen.Bounds;
|
||||
mmi.ptMaxPosition.x = wa.Left - bounds.Left;
|
||||
mmi.ptMaxPosition.y = wa.Top - bounds.Top;
|
||||
mmi.ptMaxSize.x = wa.Width;
|
||||
mmi.ptMaxSize.y = wa.Height;
|
||||
}
|
||||
|
||||
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
|
||||
}
|
||||
return System.IntPtr.Zero;
|
||||
}
|
||||
'@
|
||||
}
|
||||
}
|
||||
|
||||
# Convert screen-pixel coordinates to WPF device-independent pixels (DIP)
|
||||
function ConvertTo-ScreenPointToDip {
|
||||
@@ -52,35 +118,16 @@ function Update-MainWindowChrome {
|
||||
)
|
||||
|
||||
$windowStateMaximized = [System.Windows.WindowState]::Maximized
|
||||
$chrome = [System.Windows.Shell.WindowChrome]::GetWindowChrome($Window)
|
||||
|
||||
if ($Window.WindowState -eq $windowStateMaximized) {
|
||||
$chrome = [System.Windows.Shell.WindowChrome]::GetWindowChrome($Window)
|
||||
$resizeBorder = if ($chrome) { $chrome.ResizeBorderThickness } else { [System.Windows.SystemParameters]::WindowResizeBorderThickness }
|
||||
|
||||
# Compute margins using screen bounds vs working area
|
||||
$marginLeft = $resizeBorder.Left
|
||||
$marginTop = $resizeBorder.Top
|
||||
$marginRight = $resizeBorder.Right
|
||||
$marginBottom = $resizeBorder.Bottom
|
||||
|
||||
$screen = Get-WindowScreen -Window $Window
|
||||
if ($screen) {
|
||||
$workTL = ConvertTo-ScreenPointToDip -Window $Window -X $screen.WorkingArea.Left -Y $screen.WorkingArea.Top
|
||||
$workSize = ConvertTo-ScreenPixelsToDip -Window $Window -Width $screen.WorkingArea.Width -Height $screen.WorkingArea.Height
|
||||
$screenTL = ConvertTo-ScreenPointToDip -Window $Window -X $screen.Bounds.Left -Y $screen.Bounds.Top
|
||||
$screenSize = ConvertTo-ScreenPixelsToDip -Window $Window -Width $screen.Bounds.Width -Height $screen.Bounds.Height
|
||||
|
||||
$marginLeft += ($workTL.X - $screenTL.X)
|
||||
$marginTop += ($workTL.Y - $screenTL.Y)
|
||||
$marginRight += ($screenTL.X + $screenSize.Width) - ($workTL.X + $workSize.Width)
|
||||
$marginBottom += ($screenTL.Y + $screenSize.Height) - ($workTL.Y + $workSize.Height)
|
||||
}
|
||||
|
||||
$MainBorder.Margin = [System.Windows.Thickness]::new($marginLeft, $marginTop, $marginRight, $marginBottom)
|
||||
$MainBorder.Margin = [System.Windows.Thickness]::new(0)
|
||||
$MainBorder.BorderThickness = [System.Windows.Thickness]::new(0)
|
||||
$MainBorder.CornerRadius = [System.Windows.CornerRadius]::new(0)
|
||||
$MainBorder.Effect = $null
|
||||
$TitleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(0)
|
||||
# Zero out resize borders when maximized so the entire title bar row is draggable
|
||||
if ($chrome) { $chrome.ResizeBorderThickness = [System.Windows.Thickness]::new(0) }
|
||||
}
|
||||
else {
|
||||
$MainBorder.Margin = [System.Windows.Thickness]::new(0)
|
||||
@@ -88,6 +135,7 @@ function Update-MainWindowChrome {
|
||||
$MainBorder.CornerRadius = [System.Windows.CornerRadius]::new(8)
|
||||
$MainBorder.Effect = $NormalWindowShadow
|
||||
$TitleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(8, 8, 0, 0)
|
||||
if ($chrome) { $chrome.ResizeBorderThickness = [System.Windows.Thickness]::new(5) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Hides the currently displayed bubble popup.
|
||||
|
||||
.DESCRIPTION
|
||||
Closes the bubble popup with a smooth fade-out animation (220ms). If the
|
||||
-Immediate switch is used, the popup is closed instantly without animation.
|
||||
This function is called automatically by Show-Bubble's timer and can also
|
||||
be invoked manually to dismiss the bubble early.
|
||||
|
||||
.PARAMETER Immediate
|
||||
If specified, the bubble popup is closed instantly without a fade-out
|
||||
animation. Any pending close timer is also stopped.
|
||||
|
||||
.EXAMPLE
|
||||
Hide-Bubble
|
||||
|
||||
.EXAMPLE
|
||||
Hide-Bubble -Immediate
|
||||
#>
|
||||
function Hide-Bubble {
|
||||
param (
|
||||
[Parameter(Mandatory=$false)]
|
||||
@@ -57,34 +37,6 @@ function Hide-Bubble {
|
||||
$bubblePanel.BeginAnimation([System.Windows.UIElement]::OpacityProperty, $fadeOut)
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Displays a transient bubble popup hint anchored above a target control.
|
||||
|
||||
.DESCRIPTION
|
||||
Shows a WPF popup styled as a speech bubble above the specified target
|
||||
control. The bubble fades in with a animation, displays for a configurable
|
||||
duration, then fades out. Any previously shown bubble is dismissed
|
||||
immediately before showing the new one.
|
||||
|
||||
.PARAMETER TargetControl
|
||||
The WPF Control above which the bubble popup will be placed. This
|
||||
parameter is mandatory.
|
||||
|
||||
.PARAMETER Message
|
||||
The text message to display inside the bubble. Defaults to
|
||||
'View the selected changes here'.
|
||||
|
||||
.PARAMETER DurationSeconds
|
||||
The number of seconds the bubble remains visible before auto-hiding.
|
||||
The minimum value is 1 second. Defaults to 5 seconds.
|
||||
|
||||
.EXAMPLE
|
||||
Show-Bubble -TargetControl $myButton
|
||||
|
||||
.EXAMPLE
|
||||
Show-Bubble -TargetControl $myButton -Message 'Changes saved!' -DurationSeconds 3
|
||||
#>
|
||||
function Show-Bubble {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
|
||||
@@ -1,6 +1,71 @@
|
||||
function Show-MainWindow {
|
||||
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase,System.Windows.Forms | Out-Null
|
||||
|
||||
# ---- Constrain maximized window to taskbar work area ----
|
||||
if (-not ([System.Management.Automation.PSTypeName]'Win11Debloat.MaximizedWindowHelper').Type) {
|
||||
Add-Type -Namespace Win11Debloat -Name MaximizedWindowHelper `
|
||||
-ReferencedAssemblies 'PresentationFramework','System.Windows.Forms','System.Drawing' `
|
||||
-MemberDefinition @'
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct MINMAXINFO {
|
||||
public POINT ptReserved, ptMaxSize, ptMaxPosition, ptMinTrackSize, ptMaxTrackSize;
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct POINT { public int x, y; }
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
||||
private static extern System.IntPtr MonitorFromWindow(System.IntPtr hwnd, uint dwFlags);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
||||
private static extern bool GetMonitorInfo(System.IntPtr hMonitor, ref MONITORINFO lpmi);
|
||||
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
private struct RECT {
|
||||
public int Left, Top, Right, Bottom;
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
||||
private struct MONITORINFO {
|
||||
public int cbSize;
|
||||
public RECT rcMonitor;
|
||||
public RECT rcWork;
|
||||
public uint dwFlags;
|
||||
}
|
||||
|
||||
public static System.IntPtr WmGetMinMaxInfoHook(
|
||||
System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) {
|
||||
if (msg == 0x0024) { // WM_GETMINMAXINFO
|
||||
var mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(
|
||||
lParam, typeof(MINMAXINFO));
|
||||
|
||||
const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
|
||||
var monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
var monitorInfo = new MONITORINFO();
|
||||
monitorInfo.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(MONITORINFO));
|
||||
|
||||
if (monitor != System.IntPtr.Zero && GetMonitorInfo(monitor, ref monitorInfo)) {
|
||||
mmi.ptMaxPosition.x = monitorInfo.rcWork.Left - monitorInfo.rcMonitor.Left;
|
||||
mmi.ptMaxPosition.y = monitorInfo.rcWork.Top - monitorInfo.rcMonitor.Top;
|
||||
mmi.ptMaxSize.x = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
|
||||
mmi.ptMaxSize.y = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;
|
||||
}
|
||||
else {
|
||||
var screen = System.Windows.Forms.Screen.FromHandle(hwnd);
|
||||
var wa = screen.WorkingArea;
|
||||
var bounds = screen.Bounds;
|
||||
mmi.ptMaxPosition.x = wa.Left - bounds.Left;
|
||||
mmi.ptMaxPosition.y = wa.Top - bounds.Top;
|
||||
mmi.ptMaxSize.x = wa.Width;
|
||||
mmi.ptMaxSize.y = wa.Height;
|
||||
}
|
||||
|
||||
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
|
||||
}
|
||||
return System.IntPtr.Zero;
|
||||
}
|
||||
'@
|
||||
}
|
||||
|
||||
$WinVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' CurrentBuild
|
||||
$usesDarkMode = GetSystemUsesDarkMode
|
||||
|
||||
@@ -58,6 +123,12 @@
|
||||
$window.Add_SourceInitialized({
|
||||
& $applyInitialWindowSize
|
||||
& $updateWindowChrome
|
||||
|
||||
$hwndHelper = New-Object System.Windows.Interop.WindowInteropHelper($window)
|
||||
$hwndSource = [System.Windows.Interop.HwndSource]::FromHwnd($hwndHelper.Handle)
|
||||
$hookMethod = [Win11Debloat.MaximizedWindowHelper].GetMethod('WmGetMinMaxInfoHook')
|
||||
$hook = [System.Delegate]::CreateDelegate([System.Windows.Interop.HwndSourceHook], $hookMethod)
|
||||
$hwndSource.AddHook($hook)
|
||||
})
|
||||
|
||||
$window.Add_SizeChanged({
|
||||
@@ -88,7 +159,7 @@
|
||||
$menuReportBug.Add_Click({ Start-Process "https://github.com/Raphire/Win11Debloat/issues" })
|
||||
|
||||
$menuLogs.Add_Click({
|
||||
$logsFolder = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) 'Logs'
|
||||
$logsFolder = Split-Path $script:DefaultLogPath -Parent
|
||||
if (Test-Path $logsFolder) {
|
||||
Start-Process "explorer.exe" -ArgumentList $logsFolder
|
||||
}
|
||||
|
||||
@@ -1,24 +1,3 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Displays the Restore Backup wizard dialog.
|
||||
|
||||
.DESCRIPTION
|
||||
Presents a modal wizard that lets the user choose and restore either a
|
||||
registry backup or a Start Menu pinned-apps backup. Returns the user's
|
||||
selection via $window.Tag.
|
||||
|
||||
.PARAMETER Owner
|
||||
Optional parent WPF Window used to host this modal dialog. Defaults to the
|
||||
shared $script:GuiWindow when not supplied.
|
||||
|
||||
.OUTPUTS
|
||||
Hashtable
|
||||
Returns a Hashtable describing the user's choice. Possible shapes:
|
||||
RestoreRegistry - @{ Result='RestoreRegistry'; Backup=<normalizedBackup> }
|
||||
RestoreStartMenu - @{ Result='RestoreStartMenu'; StartMenuScope=<scope>;
|
||||
UseManualBackupFile=<bool>; BackupFilePath=<path|string> }
|
||||
Cancelled - @{ Result='Cancelled' } (from New-RestoreDialogState)
|
||||
#>
|
||||
function Show-RestoreBackupDialog {
|
||||
param(
|
||||
[System.Windows.Window]$Owner = $null
|
||||
@@ -82,6 +61,7 @@ function Show-RestoreBackupDialog {
|
||||
$startMenuIntroPanel = $window.FindName('StartMenuIntroPanel')
|
||||
$startMenuScopeCombo = $window.FindName('StartMenuScopeCombo')
|
||||
$startMenuAutoBackupCheck = $window.FindName('StartMenuAutoBackupCheck')
|
||||
$startMenuAutoBackupCheck.Visibility = 'Collapsed'
|
||||
$introInfoPanel = $window.FindName('IntroInfoPanel')
|
||||
$overviewPanel = $window.FindName('OverviewPanel')
|
||||
$overviewFeaturesSection = $window.FindName('OverviewFeaturesSection')
|
||||
@@ -169,9 +149,8 @@ function Show-RestoreBackupDialog {
|
||||
return
|
||||
}
|
||||
|
||||
$isAutoBackupEnabled = ($startMenuAutoBackupCheck.IsChecked -eq $true)
|
||||
$hasSelectedManualFile = -not [string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)
|
||||
if ($isAutoBackupEnabled -or $hasSelectedManualFile) {
|
||||
$hasSelectedFile = -not [string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)
|
||||
if ($hasSelectedFile) {
|
||||
$primaryActionBtn.Content = 'Restore backup'
|
||||
}
|
||||
else {
|
||||
@@ -217,10 +196,6 @@ function Show-RestoreBackupDialog {
|
||||
$primaryActionBtn.Visibility = 'Visible'
|
||||
$primaryActionBtn.IsDefault = $true
|
||||
$chooseRegistryBtn.IsDefault = $false
|
||||
|
||||
# Show intro panel so user can configure scope & auto-detect
|
||||
$startMenuAutoBackupCheck.IsChecked = $true
|
||||
$state.SelectedStartMenuBackupFilePath = $null
|
||||
& $refreshStartMenuUi
|
||||
}
|
||||
|
||||
@@ -316,16 +291,9 @@ function Show-RestoreBackupDialog {
|
||||
}
|
||||
|
||||
Write-Host "Backup file selected: $($openDialog.FileName)"
|
||||
$selectedBackup = Load-RegistryBackupFromFile -FilePath $openDialog.FileName
|
||||
|
||||
try {
|
||||
$selectedBackup = Load-RegistryBackupFromFile -FilePath $openDialog.FileName
|
||||
|
||||
if (-not (& $showRegistryOverview -SelectedBackup $selectedBackup -SelectedBackupFilePath $openDialog.FileName)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Show-MessageBox -Owner $window -Title 'Invalid Backup File' -Message "The selected file could not be loaded:`n$($_.Exception.Message)" -Button 'OK' -Icon 'Error' | Out-Null
|
||||
if (-not (& $showRegistryOverview -SelectedBackup $selectedBackup -SelectedBackupFilePath $openDialog.FileName)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -334,15 +302,11 @@ function Show-RestoreBackupDialog {
|
||||
}
|
||||
|
||||
$handleStartMenuPrimaryAction = {
|
||||
$scope = (& $getStartMenuScopeInfo).Scope
|
||||
$useManualBackupFile = -not ($startMenuAutoBackupCheck.IsChecked -eq $true)
|
||||
|
||||
if ($useManualBackupFile -and [string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)) {
|
||||
if ([string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)) {
|
||||
$openDialog = New-Object Microsoft.Win32.OpenFileDialog
|
||||
$openDialog.Title = 'Select Start Menu Backup File'
|
||||
$openDialog.Filter = 'Start Menu backup (*.bak)|*.bak'
|
||||
$openDialog.InitialDirectory = "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState"
|
||||
$openDialog.DefaultExt = '.bak'
|
||||
$openDialog.InitialDirectory = (Join-Path $script:AppDataPath 'Backups')
|
||||
|
||||
if ($openDialog.ShowDialog($window) -ne $true) {
|
||||
return
|
||||
@@ -354,21 +318,10 @@ function Show-RestoreBackupDialog {
|
||||
return
|
||||
}
|
||||
|
||||
if (-not $useManualBackupFile) {
|
||||
$scopeInfo = & $getStartMenuScopeInfo
|
||||
$autoBackupPath = Get-StartMenuBackupPath -Scope $scopeInfo.Scope
|
||||
if ($null -eq $autoBackupPath) {
|
||||
$scopeText = $scopeInfo.SummaryText
|
||||
Show-MessageBox -Owner $window -Title 'No Backup Found' -Message "No Start Menu backup file was found for $scopeText. Uncheck 'Automatically find Start Menu backup' to select a backup file manually." -Button 'OK' -Icon 'Warning' | Out-Null
|
||||
return
|
||||
}
|
||||
$state.SelectedStartMenuBackupFilePath = if ($scopeInfo.Scope -eq 'CurrentUser') { $autoBackupPath } else { $null }
|
||||
}
|
||||
|
||||
$scope = (& $getStartMenuScopeInfo).Scope
|
||||
$window.Tag = @{
|
||||
Result = 'RestoreStartMenu'
|
||||
StartMenuScope = $scope
|
||||
UseManualBackupFile = $useManualBackupFile
|
||||
BackupFilePath = $state.SelectedStartMenuBackupFilePath
|
||||
}
|
||||
$window.DialogResult = $true
|
||||
@@ -387,16 +340,7 @@ function Show-RestoreBackupDialog {
|
||||
}
|
||||
}
|
||||
|
||||
$startMenuAutoBackupCheck.Add_Checked({
|
||||
$state.SelectedStartMenuBackupFilePath = $null
|
||||
& $refreshStartMenuUi
|
||||
})
|
||||
$startMenuAutoBackupCheck.Add_Unchecked({
|
||||
& $refreshStartMenuUi
|
||||
})
|
||||
|
||||
$startMenuScopeCombo.Add_SelectionChanged({
|
||||
$state.SelectedStartMenuBackupFilePath = $null
|
||||
& $refreshStartMenuUi
|
||||
})
|
||||
|
||||
@@ -430,7 +374,6 @@ function Show-RestoreBackupDialog {
|
||||
|
||||
if ($state.WizardStep -eq 'StartMenu') {
|
||||
$state.SelectedStartMenuBackupFilePath = $null
|
||||
$startMenuAutoBackupCheck.IsChecked = $true
|
||||
}
|
||||
|
||||
& $setWizardStep 'SelectType'
|
||||
|
||||
@@ -40,7 +40,6 @@ function Show-RestoreBackupWindow {
|
||||
}
|
||||
elseif ($dialogResult.Result -eq 'RestoreStartMenu') {
|
||||
$scope = $dialogResult.StartMenuScope
|
||||
$useManualBackupFile = ($dialogResult.UseManualBackupFile -eq $true)
|
||||
$backupFilePath = $null
|
||||
if ($dialogResult -is [hashtable] -and $dialogResult.ContainsKey('BackupFilePath')) {
|
||||
$backupFilePath = $dialogResult['BackupFilePath']
|
||||
@@ -49,7 +48,7 @@ function Show-RestoreBackupWindow {
|
||||
$backupFilePath = $dialogResult.BackupFilePath
|
||||
}
|
||||
|
||||
if ($useManualBackupFile -and [string]::IsNullOrWhiteSpace($backupFilePath)) {
|
||||
if ([string]::IsNullOrWhiteSpace($backupFilePath)) {
|
||||
throw 'Start Menu restore canceled: no backup file selected.'
|
||||
}
|
||||
|
||||
|
||||
219
Scripts/Get-Dev.ps1
Normal file
219
Scripts/Get-Dev.ps1
Normal file
@@ -0,0 +1,219 @@
|
||||
param (
|
||||
[switch]$CLI,
|
||||
[switch]$Silent,
|
||||
[switch]$Verbose,
|
||||
[switch]$Sysprep,
|
||||
[string]$LogPath,
|
||||
[string]$User,
|
||||
[switch]$NoRestartExplorer,
|
||||
[switch]$CreateRestorePoint,
|
||||
[switch]$RunDefaults,
|
||||
[switch]$RunDefaultsLite,
|
||||
[switch]$RunSavedSettings,
|
||||
[string]$Config,
|
||||
[string]$Apps,
|
||||
[string]$AppRemovalTarget,
|
||||
[switch]$RemoveApps,
|
||||
[switch]$RemoveGamingApps,
|
||||
[switch]$RemoveHPApps,
|
||||
[switch]$ForceRemoveEdge,
|
||||
[switch]$DisableDVR,
|
||||
[switch]$DisableGameBarIntegration,
|
||||
[switch]$EnableWindowsSandbox,
|
||||
[switch]$EnableWindowsSubsystemForLinux,
|
||||
[switch]$DisableTelemetry,
|
||||
[switch]$DisableSearchHistory,
|
||||
[switch]$DisableFastStartup,
|
||||
[switch]$DisableBitlockerAutoEncryption,
|
||||
[switch]$DisableModernStandbyNetworking,
|
||||
[switch]$DisableStorageSense,
|
||||
[switch]$DisableUpdateASAP,
|
||||
[switch]$PreventUpdateAutoReboot,
|
||||
[switch]$DisableDeliveryOptimization,
|
||||
[switch]$DisableBing,
|
||||
[switch]$DisableStoreSearchSuggestions,
|
||||
[switch]$DisableDesktopSpotlight,
|
||||
[switch]$DisableLockscreenTips,
|
||||
[switch]$DisableSuggestions,
|
||||
[switch]$DisableLocationServices,
|
||||
[switch]$DisableFindMyDevice,
|
||||
[switch]$DisableEdgeAds,
|
||||
[switch]$DisableBraveBloat,
|
||||
[switch]$DisableSettings365Ads,
|
||||
[switch]$DisableSettingsHome,
|
||||
[switch]$ShowHiddenFolders,
|
||||
[switch]$ShowKnownFileExt,
|
||||
[switch]$HideDupliDrive,
|
||||
[switch]$EnableDarkMode,
|
||||
[switch]$DisableTransparency,
|
||||
[switch]$DisableAnimations,
|
||||
[switch]$TaskbarAlignLeft,
|
||||
[switch]$CombineTaskbarAlways, [switch]$CombineTaskbarWhenFull, [switch]$CombineTaskbarNever,
|
||||
[switch]$CombineMMTaskbarAlways, [switch]$CombineMMTaskbarWhenFull, [switch]$CombineMMTaskbarNever,
|
||||
[switch]$MMTaskbarModeAll, [switch]$MMTaskbarModeMainActive, [switch]$MMTaskbarModeActive,
|
||||
[switch]$HideSearchTb, [switch]$ShowSearchIconTb, [switch]$ShowSearchLabelTb, [switch]$ShowSearchBoxTb,
|
||||
[switch]$HideTaskview,
|
||||
[switch]$DisableStartRecommended,
|
||||
[switch]$DisableStartAllApps, [switch]$StartAllAppsCategory, [switch]$StartAllAppsGrid, [switch]$StartAllAppsList,
|
||||
[switch]$DisableStartPhoneLink,
|
||||
[switch]$DisableCopilot,
|
||||
[switch]$DisableRecall,
|
||||
[switch]$DisableClickToDo,
|
||||
[switch]$DisableAISvcAutoStart,
|
||||
[switch]$DisablePaintAI,
|
||||
[switch]$DisableNotepadAI,
|
||||
[switch]$DisableEdgeAI,
|
||||
[switch]$DisableSearchHighlights,
|
||||
[switch]$DisableWidgets,
|
||||
[switch]$HideChat,
|
||||
[switch]$EnableEndTask,
|
||||
[switch]$EnableLastActiveClick,
|
||||
[switch]$ClearStart,
|
||||
[string]$ReplaceStart,
|
||||
[switch]$ClearStartAllUsers,
|
||||
[string]$ReplaceStartAllUsers,
|
||||
[switch]$RevertContextMenu,
|
||||
[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,
|
||||
[switch]$ExplorerToThisPC,
|
||||
[switch]$ExplorerToDownloads,
|
||||
[switch]$ExplorerToOneDrive,
|
||||
[switch]$AddFoldersToThisPC,
|
||||
[switch]$HideOnedrive,
|
||||
[switch]$Hide3dObjects,
|
||||
[switch]$HideMusic,
|
||||
[switch]$HideIncludeInLibrary,
|
||||
[switch]$HideGiveAccessTo,
|
||||
[switch]$HideShare,
|
||||
[switch]$ShowDriveLettersFirst,
|
||||
[switch]$ShowDriveLettersLast,
|
||||
[switch]$ShowNetworkDriveLettersFirst,
|
||||
[switch]$HideDriveLetters
|
||||
)
|
||||
|
||||
# Show error if current powershell environment does not have LanguageMode set to FullLanguage
|
||||
if ($ExecutionContext.SessionState.LanguageMode -ne "FullLanguage") {
|
||||
Write-Host "Error: Win11Debloat is unable to run on your system. PowerShell execution is restricted by security policies" -ForegroundColor Red
|
||||
Write-Output ""
|
||||
Write-Output "Press enter to exit..."
|
||||
Read-Host | Out-Null
|
||||
Exit
|
||||
}
|
||||
|
||||
Clear-Host
|
||||
Write-Output "-------------------------------------------------------------------------------------------"
|
||||
Write-Output " Win11Debloat Script - Get Dev"
|
||||
Write-Output "-------------------------------------------------------------------------------------------"
|
||||
|
||||
$tempRootPath = $env:TEMP
|
||||
$tempWorkPath = Join-Path $tempRootPath 'Win11Debloat'
|
||||
$tempArchivePath = Join-Path $tempRootPath 'win11debloat.zip'
|
||||
|
||||
Write-Output "> Downloading Win11Debloat for development..."
|
||||
|
||||
# Download latest version of Win11Debloat from GitHub master branch as zip archive
|
||||
try {
|
||||
Invoke-RestMethod "https://github.com/Raphire/Win11Debloat/archive/refs/heads/master.zip" -OutFile $tempArchivePath
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error: Unable to fetch master branch from GitHub. Please check your internet connection and try again." -ForegroundColor Red
|
||||
Write-Output ""
|
||||
Write-Output "Press enter to exit..."
|
||||
Read-Host | Out-Null
|
||||
Exit
|
||||
}
|
||||
|
||||
# Migrate old user data from previous runs to AppData before cleanup
|
||||
if (Test-Path $tempWorkPath) {
|
||||
$appDataPath = Join-Path $env:LOCALAPPDATA 'Win11Debloat'
|
||||
if (-not (Test-Path $appDataPath)) { New-Item -ItemType Directory -Path $appDataPath -Force | Out-Null }
|
||||
|
||||
$oldBackupsDir = Join-Path $tempWorkPath 'Backups'
|
||||
$oldLogsDir = Join-Path $tempWorkPath 'Logs'
|
||||
$oldSettingsFile = Join-Path $tempWorkPath 'Config\LastUsedSettings.json'
|
||||
|
||||
if ((Test-Path $oldBackupsDir) -and (Get-ChildItem -Path $oldBackupsDir -ErrorAction SilentlyContinue)) {
|
||||
$newBackupsDir = Join-Path $appDataPath 'Backups'
|
||||
if (-not (Test-Path $newBackupsDir)) { New-Item -ItemType Directory -Path $newBackupsDir -Force | Out-Null }
|
||||
Get-ChildItem -Path $oldBackupsDir | Move-Item -Destination $newBackupsDir -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if ((Test-Path $oldLogsDir) -and (Get-ChildItem -Path $oldLogsDir -ErrorAction SilentlyContinue)) {
|
||||
$newLogsDir = Join-Path $appDataPath 'Logs'
|
||||
if (-not (Test-Path $newLogsDir)) { New-Item -ItemType Directory -Path $newLogsDir -Force | Out-Null }
|
||||
Get-ChildItem -Path $oldLogsDir | Move-Item -Destination $newLogsDir -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (Test-Path $oldSettingsFile) {
|
||||
Move-Item -Path $oldSettingsFile -Destination $appDataPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "> Cleaning up old Win11Debloat folder..."
|
||||
|
||||
Remove-Item $tempWorkPath -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "> Unpacking..."
|
||||
|
||||
# Unzip archive to Win11Debloat folder
|
||||
Expand-Archive $tempArchivePath $tempWorkPath
|
||||
|
||||
# Remove archive
|
||||
Remove-Item $tempArchivePath
|
||||
|
||||
# Move files
|
||||
Get-ChildItem -Path (Join-Path $tempWorkPath '*Win11Debloat-*') -Recurse | Move-Item -Destination $tempWorkPath
|
||||
|
||||
# Make list of arguments to pass on to the script
|
||||
$arguments = $($PSBoundParameters.GetEnumerator() | ForEach-Object {
|
||||
if ($_.Value -eq $true) {
|
||||
"-$($_.Key)"
|
||||
}
|
||||
else {
|
||||
"-$($_.Key) ""$($_.Value)"""
|
||||
}
|
||||
})
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "> Launching Win11Debloat..."
|
||||
|
||||
# Minimize the powershell window when no parameters are provided
|
||||
if ($arguments.Count -eq 0) {
|
||||
$windowStyle = "Minimized"
|
||||
}
|
||||
else {
|
||||
$windowStyle = "Normal"
|
||||
}
|
||||
|
||||
# Remove Powershell 7 modules from path to prevent module loading issues in the script
|
||||
if ($PSVersionTable.PSVersion.Major -ge 7) {
|
||||
$NewPSModulePath = $env:PSModulePath -split ';' | Where-Object -FilterScript { $_ -like '*WindowsPowerShell*' }
|
||||
$env:PSModulePath = $NewPSModulePath -join ';'
|
||||
}
|
||||
|
||||
# Run Win11Debloat script with the provided arguments
|
||||
$debloatScriptPath = Join-Path $tempWorkPath 'Win11Debloat.ps1'
|
||||
$debloatProcess = Start-Process powershell.exe -WindowStyle $windowStyle -PassThru -ArgumentList "-executionpolicy bypass -File `"$debloatScriptPath`" $arguments" -Verb RunAs
|
||||
|
||||
# Wait for the process to finish before continuing
|
||||
if ($null -ne $debloatProcess) {
|
||||
$debloatProcess.WaitForExit()
|
||||
}
|
||||
|
||||
# Remove all remaining script files
|
||||
if (Test-Path $tempWorkPath) {
|
||||
Write-Output ""
|
||||
Write-Output "> Cleaning up..."
|
||||
|
||||
Remove-Item $tempWorkPath -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
@@ -1,9 +1,7 @@
|
||||
param (
|
||||
[switch]$Verbose,
|
||||
[switch]$WhatIf,
|
||||
[switch]$Dev,
|
||||
[switch]$CLI,
|
||||
[switch]$Silent,
|
||||
[switch]$Verbose,
|
||||
[switch]$Sysprep,
|
||||
[string]$LogPath,
|
||||
[string]$User,
|
||||
@@ -112,7 +110,7 @@ if ($ExecutionContext.SessionState.LanguageMode -ne "FullLanguage") {
|
||||
|
||||
Clear-Host
|
||||
Write-Output "-------------------------------------------------------------------------------------------"
|
||||
Write-Output " Win11Debloat Script"
|
||||
Write-Output " Win11Debloat Script - Get"
|
||||
Write-Output "-------------------------------------------------------------------------------------------"
|
||||
|
||||
$tempRootPath = $env:TEMP
|
||||
@@ -121,48 +119,46 @@ $tempArchivePath = Join-Path $tempRootPath 'win11debloat.zip'
|
||||
|
||||
Write-Output "> Downloading Win11Debloat..."
|
||||
|
||||
# Download Win11Debloat from GitHub as a zip archive.
|
||||
# Download latest version of Win11Debloat from GitHub as zip archive
|
||||
try {
|
||||
if ($Dev) {
|
||||
$sourceUri = "https://github.com/Raphire/Win11Debloat/archive/refs/heads/master.zip"
|
||||
} else {
|
||||
$sourceUri = (Invoke-RestMethod https://api.github.com/repos/Raphire/Win11Debloat/releases/latest).zipball_url
|
||||
}
|
||||
Invoke-RestMethod $sourceUri -OutFile $tempArchivePath
|
||||
$LatestReleaseUri = (Invoke-RestMethod https://api.github.com/repos/Raphire/Win11Debloat/releases/latest).zipball_url
|
||||
Invoke-RestMethod $LatestReleaseUri -OutFile $tempArchivePath
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error: Unable to fetch required files from GitHub. Please check your internet connection and try again." -ForegroundColor Red
|
||||
Write-Host "Error: Unable to fetch latest release from GitHub. Please check your internet connection and try again." -ForegroundColor Red
|
||||
Write-Output ""
|
||||
Write-Output "Press enter to exit..."
|
||||
Read-Host | Out-Null
|
||||
Exit
|
||||
}
|
||||
|
||||
# Remove old script folder if it exists, but keep configs, logs and backups
|
||||
# Migrate old user data from previous runs to AppData before cleanup
|
||||
if (Test-Path $tempWorkPath) {
|
||||
$appDataPath = Join-Path $env:LOCALAPPDATA 'Win11Debloat'
|
||||
if (-not (Test-Path $appDataPath)) { New-Item -ItemType Directory -Path $appDataPath -Force | Out-Null }
|
||||
|
||||
$oldBackupsDir = Join-Path $tempWorkPath 'Backups'
|
||||
$oldLogsDir = Join-Path $tempWorkPath 'Logs'
|
||||
$oldSettingsFile = Join-Path $tempWorkPath 'Config\LastUsedSettings.json'
|
||||
|
||||
if ((Test-Path $oldBackupsDir) -and (Get-ChildItem -Path $oldBackupsDir -ErrorAction SilentlyContinue)) {
|
||||
$newBackupsDir = Join-Path $appDataPath 'Backups'
|
||||
if (-not (Test-Path $newBackupsDir)) { New-Item -ItemType Directory -Path $newBackupsDir -Force | Out-Null }
|
||||
Get-ChildItem -Path $oldBackupsDir | Move-Item -Destination $newBackupsDir -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if ((Test-Path $oldLogsDir) -and (Get-ChildItem -Path $oldLogsDir -ErrorAction SilentlyContinue)) {
|
||||
$newLogsDir = Join-Path $appDataPath 'Logs'
|
||||
if (-not (Test-Path $newLogsDir)) { New-Item -ItemType Directory -Path $newLogsDir -Force | Out-Null }
|
||||
Get-ChildItem -Path $oldLogsDir | Move-Item -Destination $newLogsDir -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (Test-Path $oldSettingsFile) {
|
||||
Move-Item -Path $oldSettingsFile -Destination $appDataPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "> Cleaning up old script files..."
|
||||
Write-Output "> Cleaning up old Win11Debloat folder..."
|
||||
|
||||
Get-ChildItem -Path $tempWorkPath -Exclude Config,Logs,Backups | Remove-Item -Recurse -Force
|
||||
}
|
||||
|
||||
$configDir = Join-Path $tempWorkPath 'Config'
|
||||
$backupDir = Join-Path $tempWorkPath 'ConfigOld'
|
||||
|
||||
# Temporarily move existing config files if they exist to prevent them from being overwritten by the new script files, will be moved back after the new script is unpacked
|
||||
if (Test-Path "$configDir") {
|
||||
Write-Output ""
|
||||
Write-Output "> Backing up existing config files..."
|
||||
|
||||
New-Item -ItemType Directory -Path "$backupDir" -Force | Out-Null
|
||||
|
||||
$filesToKeep = @(
|
||||
'LastUsedSettings.json'
|
||||
)
|
||||
|
||||
Get-ChildItem -Path "$configDir" -Recurse | Where-Object { $_.Name -in $filesToKeep } | Move-Item -Destination "$backupDir"
|
||||
|
||||
Remove-Item "$configDir" -Recurse -Force
|
||||
Remove-Item $tempWorkPath -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
@@ -177,21 +173,8 @@ Remove-Item $tempArchivePath
|
||||
# Move files
|
||||
Get-ChildItem -Path (Join-Path $tempWorkPath '*Win11Debloat-*') -Recurse | Move-Item -Destination $tempWorkPath
|
||||
|
||||
# Add existing config files back to Config folder
|
||||
if (Test-Path "$backupDir") {
|
||||
if (-not (Test-Path "$configDir")) {
|
||||
New-Item -ItemType Directory -Path "$configDir" -Force | Out-Null
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "> Restoring existing config files..."
|
||||
|
||||
Get-ChildItem -Path "$backupDir" -Recurse | Move-Item -Destination "$configDir"
|
||||
Remove-Item "$backupDir" -Recurse -Force
|
||||
}
|
||||
|
||||
# Make list of arguments to pass on to the script (exclude the -Dev switch, which only affects this launcher)
|
||||
$arguments = $($PSBoundParameters.GetEnumerator() | Where-Object { $_.Key -ne 'Dev' } | ForEach-Object {
|
||||
# Make list of arguments to pass on to the script
|
||||
$arguments = $($PSBoundParameters.GetEnumerator() | ForEach-Object {
|
||||
if ($_.Value -eq $true) {
|
||||
"-$($_.Key)"
|
||||
}
|
||||
@@ -226,13 +209,12 @@ if ($null -ne $debloatProcess) {
|
||||
$debloatProcess.WaitForExit()
|
||||
}
|
||||
|
||||
# Remove all remaining script files, except for configs, logs and backups
|
||||
# Remove all remaining script files
|
||||
if (Test-Path $tempWorkPath) {
|
||||
Write-Output ""
|
||||
Write-Output "> Cleaning up..."
|
||||
|
||||
# Cleanup, remove Win11Debloat directory
|
||||
Get-ChildItem -Path $tempWorkPath -Exclude Config,Logs,Backups | Remove-Item -Recurse -Force
|
||||
Remove-Item $tempWorkPath -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
|
||||
@@ -137,19 +137,19 @@ if (-not $isAdmin) {
|
||||
}
|
||||
|
||||
# Define script-level variables & paths
|
||||
$script:Version = "2026.06.24"
|
||||
$script:Version = "2026.06.14"
|
||||
$configPath = Join-Path $PSScriptRoot 'Config'
|
||||
$logsPath = Join-Path $PSScriptRoot 'Logs'
|
||||
$schemasPath = Join-Path $PSScriptRoot 'Schemas'
|
||||
$scriptsPath = Join-Path $PSScriptRoot 'Scripts'
|
||||
|
||||
$script:AppDataPath = Join-Path $env:LOCALAPPDATA 'Win11Debloat'
|
||||
$script:AppsListFilePath = Join-Path $configPath 'Apps.json'
|
||||
$script:DefaultSettingsFilePath = Join-Path $configPath 'DefaultSettings.json'
|
||||
$script:FeaturesFilePath = Join-Path $configPath 'Features.json'
|
||||
$script:SavedSettingsFilePath = Join-Path $configPath 'LastUsedSettings.json'
|
||||
$script:DefaultLogPath = Join-Path $logsPath 'Win11Debloat.log'
|
||||
$script:SavedSettingsFilePath = Join-Path $script:AppDataPath 'LastUsedSettings.json'
|
||||
$script:DefaultLogPath = Join-Path (Join-Path $script:AppDataPath 'Logs') 'Win11Debloat.log'
|
||||
$script:RegfilesPath = Join-Path $PSScriptRoot 'Regfiles'
|
||||
$script:RegistryBackupsPath = Join-Path $PSScriptRoot 'Backups'
|
||||
$script:RegistryBackupsPath = Join-Path $script:AppDataPath 'Backups'
|
||||
$script:AssetsPath = Join-Path $PSScriptRoot 'Assets'
|
||||
$script:AppSelectionSchema = Join-Path $schemasPath 'AppSelectionWindow.xaml'
|
||||
$script:MainWindowSchema = Join-Path $schemasPath 'MainWindow.xaml'
|
||||
@@ -212,6 +212,9 @@ Write-Host ""
|
||||
Write-Host ""
|
||||
|
||||
# Log script output to 'Win11Debloat.log' at the specified path
|
||||
$logDir = if ($LogPath) { $LogPath } else { Split-Path $script:DefaultLogPath -Parent }
|
||||
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
|
||||
|
||||
if ($LogPath -and (Test-Path $LogPath)) {
|
||||
Start-Transcript -Path (Join-Path $LogPath 'Win11Debloat.log') -Append -IncludeInvocationHeader -Force | Out-Null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user