mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-05-18 11:46:18 +00:00
404 lines
14 KiB
PowerShell
404 lines
14 KiB
PowerShell
function Show-RestoreBackupDialog {
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[System.Windows.Window]$Owner = $null
|
|
)
|
|
|
|
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase | Out-Null
|
|
|
|
$usesDarkMode = GetSystemUsesDarkMode
|
|
$ownerWindow = if ($Owner) { $Owner } else { $script:GuiWindow }
|
|
|
|
$overlay = $null
|
|
$overlayWasAlreadyVisible = $false
|
|
if ($ownerWindow) {
|
|
try {
|
|
$overlay = $ownerWindow.FindName('ModalOverlay')
|
|
if ($overlay) {
|
|
$overlayWasAlreadyVisible = ($overlay.Visibility -eq 'Visible')
|
|
if (-not $overlayWasAlreadyVisible) {
|
|
$ownerWindow.Dispatcher.Invoke([action]{ $overlay.Visibility = 'Visible' })
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
$schemaPath = $script:RestoreBackupWindowSchema
|
|
if (-not $schemaPath -or -not (Test-Path $schemaPath)) {
|
|
throw 'Restore backup window schema file could not be found.'
|
|
}
|
|
|
|
$xaml = Get-Content -Path $schemaPath -Raw
|
|
|
|
$reader = [System.Xml.XmlReader]::Create([System.IO.StringReader]::new($xaml))
|
|
try {
|
|
$window = [System.Windows.Markup.XamlReader]::Load($reader)
|
|
}
|
|
finally {
|
|
$reader.Close()
|
|
}
|
|
|
|
if ($ownerWindow) {
|
|
try {
|
|
$window.Owner = $ownerWindow
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
try {
|
|
SetWindowThemeResources -window $window -usesDarkMode $usesDarkMode
|
|
}
|
|
catch { }
|
|
|
|
$titleBar = $window.FindName('TitleBar')
|
|
$titleText = $window.FindName('TitleText')
|
|
$closeBtn = $window.FindName('CloseBtn')
|
|
$backBtn = $window.FindName('BackBtn')
|
|
$primaryActionBtn = $window.FindName('PrimaryActionBtn')
|
|
$chooseRegistryBtn = $window.FindName('ChooseRegistryBtn')
|
|
$chooseStartMenuBtn = $window.FindName('ChooseStartMenuBtn')
|
|
$restoreModeTabs = $window.FindName('RestoreModeTabs')
|
|
$startMenuIntroPanel = $window.FindName('StartMenuIntroPanel')
|
|
$startMenuScopeCombo = $window.FindName('StartMenuScopeCombo')
|
|
$startMenuAutoBackupCheck = $window.FindName('StartMenuAutoBackupCheck')
|
|
$introInfoPanel = $window.FindName('IntroInfoPanel')
|
|
$overviewPanel = $window.FindName('OverviewPanel')
|
|
$overviewFeaturesSection = $window.FindName('OverviewFeaturesSection')
|
|
$overviewSummaryText = $window.FindName('OverviewSummaryText')
|
|
$backupFileText = $window.FindName('BackupFileText')
|
|
$backupCreatedText = $window.FindName('BackupCreatedText')
|
|
$backupTargetText = $window.FindName('BackupTargetText')
|
|
$featuresItemsControl = $window.FindName('FeaturesItemsControl')
|
|
$nonRevertibleSeparator = $window.FindName('NonRevertibleSeparator')
|
|
$nonRevertiblePanel = $window.FindName('NonRevertiblePanel')
|
|
$nonRevertibleFeaturesItemsControl = $window.FindName('NonRevertibleFeaturesItemsControl')
|
|
$nonRevertibleWikiLink = $window.FindName('NonRevertibleWikiLink')
|
|
|
|
$titleBar.Add_MouseLeftButtonDown({ $window.DragMove() })
|
|
$window.Tag = New-RestoreDialogState
|
|
$chooseRegistryBtn.IsDefault = $true
|
|
|
|
$state = @{ WizardStep = 'SelectType'; SelectedRegistryBackup = $null; SelectedStartMenuBackupFilePath = $null }
|
|
|
|
$getStartMenuScopeInfo = {
|
|
$isAllUsersScope = ($startMenuScopeCombo.SelectedItem.Tag -eq 'AllUsers')
|
|
$scopeValue = if ($isAllUsersScope) { 'AllUsers' } else { 'CurrentUser' }
|
|
$summaryScopeText = if ($isAllUsersScope) { 'all users' } else { 'the current user' }
|
|
|
|
return [PSCustomObject]@{
|
|
Scope = $scopeValue
|
|
Target = $scopeValue
|
|
SummaryText = $summaryScopeText
|
|
}
|
|
}
|
|
|
|
$showStartMenuIntroState = {
|
|
$backupFileText.Text = 'Not selected'
|
|
$backupCreatedText.Text = 'N/A'
|
|
$overviewSummaryText.Visibility = 'Collapsed'
|
|
$overviewPanel.Visibility = 'Collapsed'
|
|
$startMenuIntroPanel.Visibility = 'Visible'
|
|
$restoreModeTabs.SelectedIndex = 2
|
|
}
|
|
|
|
$showStartMenuOverviewState = {
|
|
param([string]$BackupFilePath)
|
|
|
|
$scopeInfo = & $getStartMenuScopeInfo
|
|
$backupTargetText.Text = GetFriendlyRegistryBackupTarget -Target $scopeInfo.Target
|
|
$overviewSummaryText.Text = "This will replace the current Start Menu pinned apps layout for $($scopeInfo.SummaryText) with the selected backup."
|
|
$backupFileText.Text = Split-Path -Path $BackupFilePath -Leaf
|
|
|
|
$createdText = 'Unknown'
|
|
try {
|
|
$createdText = (Get-Item -LiteralPath $BackupFilePath -ErrorAction Stop).LastWriteTime.ToString('yyyy-MM-dd HH:mm')
|
|
}
|
|
catch { }
|
|
$backupCreatedText.Text = $createdText
|
|
|
|
$overviewFeaturesSection.Visibility = 'Collapsed'
|
|
$overviewSummaryText.Visibility = 'Visible'
|
|
$nonRevertibleSeparator.Visibility = 'Collapsed'
|
|
$nonRevertiblePanel.Visibility = 'Collapsed'
|
|
$introInfoPanel.Visibility = 'Collapsed'
|
|
$overviewPanel.Visibility = 'Visible'
|
|
$restoreModeTabs.SelectedIndex = 1
|
|
}
|
|
|
|
$updateStartMenuOverviewPanel = {
|
|
if ($state.WizardStep -ne 'StartMenu') {
|
|
return
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)) {
|
|
& $showStartMenuIntroState
|
|
return
|
|
}
|
|
|
|
& $showStartMenuOverviewState $state.SelectedStartMenuBackupFilePath
|
|
}
|
|
|
|
$updateStartMenuPrimaryActionText = {
|
|
if ($state.WizardStep -ne 'StartMenu') {
|
|
return
|
|
}
|
|
|
|
$isAutoBackupEnabled = ($startMenuAutoBackupCheck.IsChecked -eq $true)
|
|
$hasSelectedManualFile = -not [string]::IsNullOrWhiteSpace($state.SelectedStartMenuBackupFilePath)
|
|
if ($isAutoBackupEnabled -or $hasSelectedManualFile) {
|
|
$primaryActionBtn.Content = 'Restore backup'
|
|
}
|
|
else {
|
|
$primaryActionBtn.Content = 'Select backup file'
|
|
}
|
|
}
|
|
|
|
$refreshStartMenuUi = {
|
|
& $updateStartMenuOverviewPanel
|
|
& $updateStartMenuPrimaryActionText
|
|
}
|
|
|
|
$enterSelectTypeStep = {
|
|
$titleText.Text = 'Restore Backup'
|
|
$restoreModeTabs.SelectedIndex = 0
|
|
$backBtn.Visibility = 'Visible'
|
|
$backBtn.Content = 'Cancel'
|
|
$primaryActionBtn.Visibility = 'Collapsed'
|
|
$chooseRegistryBtn.IsDefault = $true
|
|
$primaryActionBtn.IsDefault = $false
|
|
}
|
|
|
|
$enterRegistryStep = {
|
|
$titleText.Text = 'Restore Registry Backup'
|
|
$restoreModeTabs.SelectedIndex = 1
|
|
$introInfoPanel.Visibility = 'Visible'
|
|
$overviewPanel.Visibility = 'Collapsed'
|
|
$overviewFeaturesSection.Visibility = 'Visible'
|
|
$overviewSummaryText.Visibility = 'Collapsed'
|
|
$backBtn.Visibility = 'Visible'
|
|
$backBtn.Content = 'Back'
|
|
$primaryActionBtn.Visibility = 'Visible'
|
|
$primaryActionBtn.Content = 'Select backup file'
|
|
$primaryActionBtn.IsDefault = $true
|
|
$chooseRegistryBtn.IsDefault = $false
|
|
}
|
|
|
|
$enterStartMenuStep = {
|
|
$titleText.Text = 'Restore Start Menu Backup'
|
|
$restoreModeTabs.SelectedIndex = 2
|
|
$backBtn.Visibility = 'Visible'
|
|
$backBtn.Content = 'Back'
|
|
$primaryActionBtn.Visibility = 'Visible'
|
|
$primaryActionBtn.IsDefault = $true
|
|
$chooseRegistryBtn.IsDefault = $false
|
|
& $refreshStartMenuUi
|
|
}
|
|
|
|
$showRegistryOverview = {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
$SelectedBackup,
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$SelectedBackupFilePath
|
|
)
|
|
|
|
$createdText = if ([string]::IsNullOrWhiteSpace($SelectedBackup.CreatedAt)) {
|
|
'Unknown'
|
|
}
|
|
else {
|
|
try {
|
|
[DateTime]::Parse($SelectedBackup.CreatedAt).ToString('yyyy-MM-dd HH:mm')
|
|
}
|
|
catch {
|
|
$SelectedBackup.CreatedAt
|
|
}
|
|
}
|
|
|
|
$selectedFeatureIds = Get-SelectedFeatureIdsFromBackup -SelectedBackup $SelectedBackup
|
|
$featureLists = Get-RestoreBackupFeatureLists -SelectedFeatureIds $selectedFeatureIds -Features $script:Features
|
|
$revertibleFeaturesList = @($featureLists.Revertible)
|
|
$nonRevertibleFeaturesList = @($featureLists.NonRevertible)
|
|
Write-Host "Backup overview prepared. Revertible=$($revertibleFeaturesList.Count), NonRevertible=$($nonRevertibleFeaturesList.Count)"
|
|
|
|
if ($revertibleFeaturesList.Count -eq 0) {
|
|
throw 'The selected backup does not contain any changes that can be restored.'
|
|
}
|
|
|
|
$backupFileText.Text = Split-Path $SelectedBackupFilePath -Leaf
|
|
$backupCreatedText.Text = $createdText
|
|
$backupTargetText.Text = GetFriendlyRegistryBackupTarget -Target ([string]$SelectedBackup.Target)
|
|
$featuresItemsControl.ItemsSource = $revertibleFeaturesList
|
|
$overviewFeaturesSection.Visibility = 'Visible'
|
|
$overviewSummaryText.Visibility = 'Collapsed'
|
|
$nonRevertibleFeaturesItemsControl.ItemsSource = $nonRevertibleFeaturesList
|
|
|
|
$hasNonRevertibleItems = ($nonRevertibleFeaturesList.Count -gt 0)
|
|
if ($hasNonRevertibleItems) { $nonRevertiblePanel.Visibility = 'Visible' } else { $nonRevertiblePanel.Visibility = 'Collapsed' }
|
|
if ($hasNonRevertibleItems) { $nonRevertibleSeparator.Visibility = 'Visible' } else { $nonRevertibleSeparator.Visibility = 'Collapsed' }
|
|
$introInfoPanel.Visibility = 'Collapsed'
|
|
$overviewPanel.Visibility = 'Visible'
|
|
|
|
return $true
|
|
}
|
|
|
|
$handleRegistryPrimaryAction = {
|
|
if ($state.SelectedRegistryBackup) {
|
|
$window.Tag = @{
|
|
Result = 'RestoreRegistry'
|
|
Backup = $state.SelectedRegistryBackup
|
|
}
|
|
$window.DialogResult = $true
|
|
$window.Close()
|
|
return
|
|
}
|
|
|
|
$openDialog = New-Object Microsoft.Win32.OpenFileDialog
|
|
$openDialog.Title = 'Select Registry Backup File'
|
|
$openDialog.Filter = 'Registry backup (*.json)|*.json'
|
|
$openDialog.DefaultExt = '.json'
|
|
$openDialog.InitialDirectory = $script:RegistryBackupsPath
|
|
|
|
if ($openDialog.ShowDialog($window) -ne $true) {
|
|
return
|
|
}
|
|
|
|
Write-Host "Backup file selected: $($openDialog.FileName)"
|
|
$selectedBackup = Load-RegistryBackupFromFile -FilePath $openDialog.FileName
|
|
|
|
if (-not (& $showRegistryOverview -SelectedBackup $selectedBackup -SelectedBackupFilePath $openDialog.FileName)) {
|
|
return
|
|
}
|
|
|
|
$state.SelectedRegistryBackup = $selectedBackup
|
|
$primaryActionBtn.Content = 'Restore from backup'
|
|
}
|
|
|
|
$handleStartMenuPrimaryAction = {
|
|
$scope = (& $getStartMenuScopeInfo).Scope
|
|
$useManualBackupFile = -not ($startMenuAutoBackupCheck.IsChecked -eq $true)
|
|
|
|
if ($useManualBackupFile -and [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'
|
|
|
|
if ($openDialog.ShowDialog($window) -ne $true) {
|
|
return
|
|
}
|
|
|
|
$state.SelectedStartMenuBackupFilePath = $openDialog.FileName
|
|
Write-Host "Selected Start Menu backup file: $($state.SelectedStartMenuBackupFilePath)"
|
|
& $refreshStartMenuUi
|
|
return
|
|
}
|
|
|
|
$window.Tag = @{
|
|
Result = 'RestoreStartMenu'
|
|
StartMenuScope = $scope
|
|
UseManualBackupFile = $useManualBackupFile
|
|
BackupFilePath = $state.SelectedStartMenuBackupFilePath
|
|
}
|
|
$window.DialogResult = $true
|
|
$window.Close()
|
|
}
|
|
|
|
$setWizardStep = {
|
|
param([string]$step)
|
|
|
|
$state.WizardStep = $step
|
|
|
|
switch ($step) {
|
|
'SelectType' { & $enterSelectTypeStep }
|
|
'Registry' { & $enterRegistryStep }
|
|
'StartMenu' { & $enterStartMenuStep }
|
|
}
|
|
}
|
|
|
|
$startMenuAutoBackupCheck.Add_Checked({
|
|
$state.SelectedStartMenuBackupFilePath = $null
|
|
& $refreshStartMenuUi
|
|
})
|
|
$startMenuAutoBackupCheck.Add_Unchecked({
|
|
& $refreshStartMenuUi
|
|
})
|
|
|
|
$startMenuScopeCombo.Add_SelectionChanged({
|
|
& $refreshStartMenuUi
|
|
})
|
|
|
|
$nonRevertibleWikiLink.Add_MouseLeftButtonUp({
|
|
try {
|
|
Start-Process 'https://github.com/Raphire/Win11Debloat/wiki/Reverting-Changes' | Out-Null
|
|
}
|
|
catch { }
|
|
})
|
|
|
|
$closeBtn.Add_Click({
|
|
$window.Tag = New-RestoreDialogState
|
|
$window.DialogResult = $false
|
|
$window.Close()
|
|
})
|
|
|
|
$chooseRegistryBtn.Add_Click({ & $setWizardStep 'Registry' })
|
|
$chooseStartMenuBtn.Add_Click({ & $setWizardStep 'StartMenu' })
|
|
|
|
$backBtn.Add_Click({
|
|
if ($state.WizardStep -eq 'SelectType') {
|
|
$window.Tag = New-RestoreDialogState
|
|
$window.DialogResult = $false
|
|
$window.Close()
|
|
return
|
|
}
|
|
|
|
if ($state.WizardStep -eq 'Registry') {
|
|
$state.SelectedRegistryBackup = $null
|
|
}
|
|
|
|
if ($state.WizardStep -eq 'StartMenu') {
|
|
$state.SelectedStartMenuBackupFilePath = $null
|
|
$startMenuAutoBackupCheck.IsChecked = $true
|
|
}
|
|
|
|
& $setWizardStep 'SelectType'
|
|
})
|
|
|
|
$primaryActionBtn.Add_Click({
|
|
switch ($state.WizardStep) {
|
|
'Registry' { & $handleRegistryPrimaryAction }
|
|
'StartMenu' { & $handleStartMenuPrimaryAction }
|
|
}
|
|
})
|
|
|
|
$window.Add_KeyDown({
|
|
param($source, $e)
|
|
if ($e.Key -eq 'Escape') {
|
|
$window.Tag = New-RestoreDialogState
|
|
$window.DialogResult = $false
|
|
$window.Close()
|
|
}
|
|
})
|
|
|
|
& $setWizardStep 'SelectType'
|
|
|
|
try {
|
|
$null = $window.ShowDialog()
|
|
}
|
|
catch {
|
|
$innerMessage = if ($_.Exception.InnerException) { $_.Exception.InnerException.Message } else { 'None' }
|
|
throw "Failed to show restore backup dialog. Error: $($_.Exception.Message) Inner: $innerMessage"
|
|
}
|
|
finally {
|
|
if ($overlay -and -not $overlayWasAlreadyVisible) {
|
|
try {
|
|
$ownerWindow.Dispatcher.Invoke([action]{ $overlay.Visibility = 'Collapsed' })
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
return $window.Tag
|
|
}
|