mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-08-21 23:26:42 +00:00
feat: improve consistency checks and error reporting
This commit is contained in:
@@ -506,20 +506,15 @@ function Import-Configuration {
|
||||
return
|
||||
}
|
||||
|
||||
if (-not $config.Version) {
|
||||
Write-Error "Invalid configuration file format: '$($openDialog.FileName)'"
|
||||
Show-MessageBox -Message "Invalid configuration file format." -Title 'Invalid Config' -Button 'OK' -Icon 'Error' | Out-Null
|
||||
$consistencyError = Test-ConfigConsistency -Config $config
|
||||
if ($consistencyError) {
|
||||
Write-Error "Invalid configuration file '$($openDialog.FileName)': $consistencyError"
|
||||
Show-MessageBox -Message "Invalid configuration file: $consistencyError" -Title 'Invalid Config' -Button 'OK' -Icon 'Error' | Out-Null
|
||||
return
|
||||
}
|
||||
|
||||
$availableCategories = Get-AvailableImportExportCategories -Config $config
|
||||
|
||||
if ($availableCategories.Count -eq 0) {
|
||||
Write-Warning "Configuration file '$($openDialog.FileName)' contains no importable data."
|
||||
Show-MessageBox -Message "The selected file contains no importable data." -Title 'Invalid Config' -Button 'OK' -Icon 'Error' | Out-Null
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Available categories in config: $($availableCategories -join ', ')"
|
||||
|
||||
$appCount = @($config.Apps | Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) }).Count
|
||||
|
||||
@@ -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,56 @@
|
||||
<#
|
||||
.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.'
|
||||
}
|
||||
|
||||
$lookup = @{}
|
||||
foreach ($setting in @($Config.Deployment)) {
|
||||
if ($setting -and $setting.Name) {
|
||||
$lookup[$setting.Name] = $setting.Value
|
||||
}
|
||||
}
|
||||
|
||||
$hasScope = $lookup.ContainsKey('AppRemovalScopeIndex')
|
||||
$hasUser = $lookup.ContainsKey('UserSelectionIndex')
|
||||
|
||||
# "Current user only" (index 1) is only valid together with "Current User" (index 0)
|
||||
if ($hasScope -and [int]$lookup['AppRemovalScopeIndex'] -eq 1) {
|
||||
if (-not $hasUser -or [int]$lookup['UserSelectionIndex'] -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 [int]$lookup['AppRemovalScopeIndex'] -eq 2) {
|
||||
if (-not $hasUser -or [int]$lookup['UserSelectionIndex'] -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
|
||||
}
|
||||
@@ -2,6 +2,7 @@ BeforeAll {
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-JsonFile.ps1')
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Add-Parameter.ps1')
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Import-ConfigToParams.ps1')
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Test-ConfigConsistency.ps1')
|
||||
$script:ConfigFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading\ExportedConfig.WithSettings.json'
|
||||
$script:SkipRegistryBackupFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading\ExportedConfig.SkipRegistryBackup.json'
|
||||
}
|
||||
@@ -44,3 +45,87 @@ Describe 'Import-ConfigToParams' {
|
||||
$script:Params['SkipRegistryBackup'] | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Test-ConfigConsistency' {
|
||||
It 'reports an error for an empty config' {
|
||||
Test-ConfigConsistency -Config $null | Should -Match 'empty or could not be read'
|
||||
}
|
||||
|
||||
It 'reports an error for a config missing a Version' {
|
||||
$config = [PSCustomObject]@{ Tweaks = @( @{ Name = 'DisableTelemetry'; Value = $true } ) }
|
||||
Test-ConfigConsistency -Config $config | Should -Match 'missing a Version'
|
||||
}
|
||||
|
||||
It 'reports an error for a config with no importable data' {
|
||||
$config = [PSCustomObject]@{ Version = '1.0' }
|
||||
Test-ConfigConsistency -Config $config | Should -Match 'no importable data'
|
||||
}
|
||||
|
||||
It 'returns null for a consistent all-users scope' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 0 }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 0 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'returns null for target-user scope combined with Other User and a username' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 1 }
|
||||
@{ Name = 'OtherUsername'; Value = 'jdoe' }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 2 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'returns null for current-user-only scope combined with Current User' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 0 }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 1 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'reports an error for current-user-only scope without Current User selected' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 1 }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 1 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -Match "requires the deployment target 'Current User'"
|
||||
}
|
||||
|
||||
It 'reports an error for target-user scope without Other User selected' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 0 }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 2 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -Match "requires the deployment target 'Other User'"
|
||||
}
|
||||
|
||||
It 'reports an error for target-user scope with a blank username' {
|
||||
$config = [PSCustomObject]@{
|
||||
Version = '1.0'
|
||||
Deployment = @(
|
||||
@{ Name = 'UserSelectionIndex'; Value = 1 }
|
||||
@{ Name = 'OtherUsername'; Value = ' ' }
|
||||
@{ Name = 'AppRemovalScopeIndex'; Value = 2 }
|
||||
)
|
||||
}
|
||||
Test-ConfigConsistency -Config $config | Should -Match "requires an 'OtherUsername' value"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,6 +427,7 @@ if (-not $script:WingetInstalled -and -not $Silent) {
|
||||
. "$PSScriptRoot/Scripts/Helpers/Get-FriendlyTargetUserName.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Get-RebootFeatureLabels.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Import-ConfigToParams.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Test-ConfigConsistency.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Get-TargetUserForAppRemoval.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Get-RegFileOperations.ps1"
|
||||
. "$PSScriptRoot/Scripts/Helpers/Test-TargetUserName.ps1"
|
||||
|
||||
Reference in New Issue
Block a user