mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-08-23 08:02:07 +00:00
feat: improve consistency checks and error reporting
This commit is contained in:
@@ -506,20 +506,15 @@ function Import-Configuration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $config.Version) {
|
$consistencyError = Test-ConfigConsistency -Config $config
|
||||||
Write-Error "Invalid configuration file format: '$($openDialog.FileName)'"
|
if ($consistencyError) {
|
||||||
Show-MessageBox -Message "Invalid configuration file format." -Title 'Invalid Config' -Button 'OK' -Icon 'Error' | Out-Null
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$availableCategories = Get-AvailableImportExportCategories -Config $config
|
$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 ', ')"
|
Write-Host "Available categories in config: $($availableCategories -join ', ')"
|
||||||
|
|
||||||
$appCount = @($config.Apps | Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) }).Count
|
$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"
|
throw "Failed to read config file: $resolvedConfigPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$consistencyError = Test-ConfigConsistency -Config $configJson
|
||||||
|
if ($consistencyError) {
|
||||||
|
throw "Invalid config file '$resolvedConfigPath': $consistencyError"
|
||||||
|
}
|
||||||
|
|
||||||
$importedItems = 0
|
$importedItems = 0
|
||||||
|
|
||||||
if ($configJson.Apps) {
|
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\FileIO\Import-JsonFile.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Add-Parameter.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Add-Parameter.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Import-ConfigToParams.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:ConfigFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading\ExportedConfig.WithSettings.json'
|
||||||
$script:SkipRegistryBackupFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading\ExportedConfig.SkipRegistryBackup.json'
|
$script:SkipRegistryBackupFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading\ExportedConfig.SkipRegistryBackup.json'
|
||||||
}
|
}
|
||||||
@@ -44,3 +45,87 @@ Describe 'Import-ConfigToParams' {
|
|||||||
$script:Params['SkipRegistryBackup'] | Should -BeTrue
|
$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-FriendlyTargetUserName.ps1"
|
||||||
. "$PSScriptRoot/Scripts/Helpers/Get-RebootFeatureLabels.ps1"
|
. "$PSScriptRoot/Scripts/Helpers/Get-RebootFeatureLabels.ps1"
|
||||||
. "$PSScriptRoot/Scripts/Helpers/Import-ConfigToParams.ps1"
|
. "$PSScriptRoot/Scripts/Helpers/Import-ConfigToParams.ps1"
|
||||||
|
. "$PSScriptRoot/Scripts/Helpers/Test-ConfigConsistency.ps1"
|
||||||
. "$PSScriptRoot/Scripts/Helpers/Get-TargetUserForAppRemoval.ps1"
|
. "$PSScriptRoot/Scripts/Helpers/Get-TargetUserForAppRemoval.ps1"
|
||||||
. "$PSScriptRoot/Scripts/Helpers/Get-RegFileOperations.ps1"
|
. "$PSScriptRoot/Scripts/Helpers/Get-RegFileOperations.ps1"
|
||||||
. "$PSScriptRoot/Scripts/Helpers/Test-TargetUserName.ps1"
|
. "$PSScriptRoot/Scripts/Helpers/Test-TargetUserName.ps1"
|
||||||
|
|||||||
Reference in New Issue
Block a user