mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-10-08 06:26:45 +00:00
Improve error reporting & handling (#741)
This commit is contained in:
@@ -191,6 +191,13 @@ function Invoke-RegistryOperation {
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Applies all parsed operations from a registry file.
|
||||
|
||||
.OUTPUTS
|
||||
System.Boolean. $true when all operations complete, including WhatIf; otherwise $false.
|
||||
#>
|
||||
function Invoke-RegistryOperationsFromRegFile {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -203,7 +210,7 @@ function Invoke-RegistryOperationsFromRegFile {
|
||||
|
||||
if ($script:Params.ContainsKey("WhatIf")) {
|
||||
Write-Host "[WhatIf] Apply $totalOperations registry changes from '$RegFilePath'" -ForegroundColor Cyan
|
||||
return
|
||||
return $true
|
||||
}
|
||||
|
||||
foreach ($operation in $operations) {
|
||||
@@ -222,5 +229,8 @@ function Invoke-RegistryOperationsFromRegFile {
|
||||
|
||||
if ($accessDeniedCount -gt 0) {
|
||||
Write-Warning "Registry fallback import completed with $accessDeniedCount access-restricted operation(s) skipped in '$RegFilePath'."
|
||||
return $false
|
||||
}
|
||||
|
||||
return $true
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@ function Import-ConfigToParams {
|
||||
throw "Failed to read config file: $resolvedConfigPath"
|
||||
}
|
||||
|
||||
$consistencyError = Test-ConfigConsistency -Config $configJson
|
||||
if ($consistencyError) {
|
||||
throw "Invalid config file '$resolvedConfigPath': $consistencyError"
|
||||
}
|
||||
|
||||
$importedItems = 0
|
||||
|
||||
if ($configJson.Apps) {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Validates that a configuration file is structurally consistent before it is applied.
|
||||
|
||||
.DESCRIPTION
|
||||
Returns $null when the configuration is valid, otherwise a string describing the
|
||||
first problem found. Used by both the CLI and GUI import paths to reject invalid
|
||||
configs before any settings are applied.
|
||||
|
||||
.OUTPUTS
|
||||
System.String. $null when valid, otherwise an error message.
|
||||
#>
|
||||
function Test-ConfigConsistency {
|
||||
param($Config)
|
||||
|
||||
if (-not $Config) {
|
||||
return 'Configuration is empty or could not be read.'
|
||||
}
|
||||
|
||||
if (-not $Config.Version) {
|
||||
return 'Configuration is missing a Version field.'
|
||||
}
|
||||
|
||||
if (-not $Config.Apps -and -not $Config.Tweaks -and -not $Config.Deployment) {
|
||||
return 'The configuration file contains no importable data.'
|
||||
}
|
||||
|
||||
if ($null -ne $Config.Apps) {
|
||||
if ($Config.Apps -isnot [string] -and $Config.Apps -isnot [System.Collections.IEnumerable]) {
|
||||
return 'Configuration Apps entries must be strings.'
|
||||
}
|
||||
foreach ($app in @($Config.Apps)) {
|
||||
if ($app -isnot [string]) {
|
||||
return 'Configuration Apps entries must be strings.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($categoryName in @('Tweaks', 'Deployment')) {
|
||||
$category = $Config.$categoryName
|
||||
if ($null -eq $category) { continue }
|
||||
|
||||
if ($category -is [string] -or $category -isnot [System.Collections.IEnumerable]) {
|
||||
return "Configuration $categoryName entries must contain Name and Value properties."
|
||||
}
|
||||
foreach ($setting in @($category)) {
|
||||
$hasName = if ($setting -is [System.Collections.IDictionary]) { $setting.Contains('Name') } else { $null -ne $setting.PSObject.Properties['Name'] }
|
||||
$hasValue = if ($setting -is [System.Collections.IDictionary]) { $setting.Contains('Value') } else { $null -ne $setting.PSObject.Properties['Value'] }
|
||||
if (-not $setting -or -not $hasName -or -not $hasValue -or $setting.Name -isnot [string] -or [string]::IsNullOrWhiteSpace($setting.Name)) {
|
||||
return "Configuration $categoryName entries must contain Name and Value properties."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lookup = @{}
|
||||
foreach ($setting in @($Config.Deployment)) {
|
||||
if ($setting -and $setting.Name) {
|
||||
$lookup[$setting.Name] = $setting.Value
|
||||
}
|
||||
}
|
||||
|
||||
$hasScope = $lookup.ContainsKey('AppRemovalScopeIndex')
|
||||
$hasUser = $lookup.ContainsKey('UserSelectionIndex')
|
||||
|
||||
$scopeIndex = $null
|
||||
if ($hasScope) {
|
||||
if (-not [int]::TryParse("$($lookup['AppRemovalScopeIndex'])", [ref]$scopeIndex) -or $scopeIndex -notin @(0, 1, 2)) {
|
||||
return 'AppRemovalScopeIndex must be a supported numeric value (0, 1, or 2).'
|
||||
}
|
||||
}
|
||||
|
||||
$userIndex = $null
|
||||
if ($hasUser) {
|
||||
if (-not [int]::TryParse("$($lookup['UserSelectionIndex'])", [ref]$userIndex) -or $userIndex -notin @(0, 1, 2)) {
|
||||
return 'UserSelectionIndex must be a supported numeric value (0, 1, or 2).'
|
||||
}
|
||||
}
|
||||
|
||||
# "Current user only" (index 1) is only valid together with "Current User" (index 0)
|
||||
if ($hasScope -and $scopeIndex -eq 1) {
|
||||
if (-not $hasUser -or $userIndex -ne 0) {
|
||||
return "App removal scope 'Current user only' (AppRemovalScopeIndex 1) requires the deployment target 'Current User' (UserSelectionIndex 0)."
|
||||
}
|
||||
}
|
||||
|
||||
# "Target user only" (index 2) is only valid together with "Other User" (index 1)
|
||||
if ($hasScope -and $scopeIndex -eq 2) {
|
||||
if (-not $hasUser -or $userIndex -ne 1) {
|
||||
return "App removal scope 'Target user only' (AppRemovalScopeIndex 2) requires the deployment target 'Other User' (UserSelectionIndex 1)."
|
||||
}
|
||||
if (-not $lookup.ContainsKey('OtherUsername') -or [string]::IsNullOrWhiteSpace("$($lookup['OtherUsername'])")) {
|
||||
return "App removal scope 'Target user only' (AppRemovalScopeIndex 2) requires an 'OtherUsername' value."
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
Reference in New Issue
Block a user