From 410c2683245a43e46a200b56f81d2b27f2748853 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:18:51 +0100 Subject: [PATCH 01/13] Spelling --- source/Public/Get-UserName.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Public/Get-UserName.ps1 b/source/Public/Get-UserName.ps1 index f79e97d..7e1d042 100644 --- a/source/Public/Get-UserName.ps1 +++ b/source/Public/Get-UserName.ps1 @@ -1,12 +1,12 @@ <# .SYNOPSIS - Returns the user name cross-plattform. + Returns the user name cross-platform. .DESCRIPTION - Returns the current user name cross-plattform. The variable `$env:USERNAME` + Returns the current user name cross-platform. The variable `$env:USERNAME` does not exist cross-platform which hinders development and testing on macOS and Linux. Instead this command can be used to get the user name - cross-plattform. + cross-platform. .OUTPUTS System.String From e7f0456311c044d4e640161b375ae529a47807e7 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:19:03 +0100 Subject: [PATCH 02/13] Fix PSSA warning --- source/Public/Assert-BoundParameter.ps1 | 1 + source/Public/Compare-ResourcePropertyState.ps1 | 1 + source/Public/ConvertFrom-DscResourceInstance.ps1 | 1 + source/Public/Get-DscProperty.ps1 | 1 + source/Public/Test-DscProperty.ps1 | 1 + 5 files changed, 5 insertions(+) diff --git a/source/Public/Assert-BoundParameter.ps1 b/source/Public/Assert-BoundParameter.ps1 index 94ecb7a..f1c2408 100644 --- a/source/Public/Assert-BoundParameter.ps1 +++ b/source/Public/Assert-BoundParameter.ps1 @@ -153,6 +153,7 @@ #> function Assert-BoundParameter { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [CmdletBinding()] param ( diff --git a/source/Public/Compare-ResourcePropertyState.ps1 b/source/Public/Compare-ResourcePropertyState.ps1 index 0e6f24c..55e8176 100644 --- a/source/Public/Compare-ResourcePropertyState.ps1 +++ b/source/Public/Compare-ResourcePropertyState.ps1 @@ -131,6 +131,7 @@ #> function Compare-ResourcePropertyState { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [CmdletBinding()] [OutputType([System.Collections.Hashtable[]])] param diff --git a/source/Public/ConvertFrom-DscResourceInstance.ps1 b/source/Public/ConvertFrom-DscResourceInstance.ps1 index 7c8ea0b..bca799f 100644 --- a/source/Public/ConvertFrom-DscResourceInstance.ps1 +++ b/source/Public/ConvertFrom-DscResourceInstance.ps1 @@ -40,6 +40,7 @@ #> function ConvertFrom-DscResourceInstance { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param diff --git a/source/Public/Get-DscProperty.ps1 b/source/Public/Get-DscProperty.ps1 index 96d59c7..7284b75 100644 --- a/source/Public/Get-DscProperty.ps1 +++ b/source/Public/Get-DscProperty.ps1 @@ -73,6 +73,7 @@ #> function Get-DscProperty { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [CmdletBinding(DefaultParameterSetName = 'Default')] [OutputType([System.Collections.Hashtable])] param diff --git a/source/Public/Test-DscProperty.ps1 b/source/Public/Test-DscProperty.ps1 index 5464edb..6ca7ba6 100644 --- a/source/Public/Test-DscProperty.ps1 +++ b/source/Public/Test-DscProperty.ps1 @@ -62,6 +62,7 @@ #> function Test-DscProperty { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] [CmdletBinding()] [OutputType([System.Boolean])] param From 7a841f066b86cbf7ebea3ae6a9e0cf2d6c5a168b Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:14:35 +0100 Subject: [PATCH 03/13] Remove ForEach-Object and Where-Object --- source/Public/Remove-CommonParameter.ps1 | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/Public/Remove-CommonParameter.ps1 b/source/Public/Remove-CommonParameter.ps1 index 36b8d3d..75530a7 100644 --- a/source/Public/Remove-CommonParameter.ps1 +++ b/source/Public/Remove-CommonParameter.ps1 @@ -35,13 +35,17 @@ function Remove-CommonParameter $inputClone = $Hashtable.Clone() - $commonParameters = [System.Management.Automation.PSCmdlet]::CommonParameters - $commonParameters += [System.Management.Automation.PSCmdlet]::OptionalCommonParameters - - $Hashtable.Keys | Where-Object -FilterScript { - $_ -in $commonParameters - } | ForEach-Object -Process { - $inputClone.Remove($_) + $commonParameters = @( + [System.Management.Automation.PSCmdlet]::CommonParameters + [System.Management.Automation.PSCmdlet]::OptionalCommonParameters + ) + + foreach ($key in $Hashtable.Keys) + { + if ($key -in $commonParameters) + { + $inputClone.Remove($key) + } } return $inputClone From fcf70618a38923db04f0ea1e2a9fb87133083c86 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:14:56 +0100 Subject: [PATCH 04/13] Add begin and end --- source/Private/Clear-ZeroedEnumPropertyValue.ps1 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/Private/Clear-ZeroedEnumPropertyValue.ps1 b/source/Private/Clear-ZeroedEnumPropertyValue.ps1 index 20b31aa..58d4eb8 100644 --- a/source/Private/Clear-ZeroedEnumPropertyValue.ps1 +++ b/source/Private/Clear-ZeroedEnumPropertyValue.ps1 @@ -27,9 +27,13 @@ function Clear-ZeroedEnumPropertyValue $InputObject ) - process + begin { $result = @{} + } + + process + { foreach ($property in $InputObject.Keys) { @@ -42,6 +46,10 @@ function Clear-ZeroedEnumPropertyValue $result.$property = $value } + } + + end + { return $result } } From 1352a2066cbd36f10b218e8078069d9bc71d551e Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:15:15 +0100 Subject: [PATCH 05/13] Use arraylist --- source/Public/Get-DscProperty.ps1 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/Public/Get-DscProperty.ps1 b/source/Public/Get-DscProperty.ps1 index 7284b75..a92736d 100644 --- a/source/Public/Get-DscProperty.ps1 +++ b/source/Public/Get-DscProperty.ps1 @@ -137,7 +137,7 @@ function Get-DscProperty { if ($PSBoundParameters.ContainsKey('Attribute')) { - $propertiesOfAttribute = @() + $propertiesOfAttribute = [System.Collections.ArrayList]::new() $propertiesOfAttribute += $property | Where-Object -FilterScript { $InputObject.GetType().GetMember($_).CustomAttributes.Where( @@ -174,9 +174,7 @@ function Get-DscProperty { if ($HasValue.IsPresent) { - $isAssigned = Test-DscPropertyIsAssigned -Name $currentProperty -InputObject $InputObject - - if (-not $isAssigned) + if (-not (Test-DscPropertyIsAssigned -Name $currentProperty -InputObject $InputObject)) { continue } From a1f9d4bb60d165500658d89207965cf38757631e Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:20:21 +0100 Subject: [PATCH 06/13] Spelling --- source/Public/Test-DscProperty.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Public/Test-DscProperty.ps1 b/source/Public/Test-DscProperty.ps1 index 6ca7ba6..e8a12d4 100644 --- a/source/Public/Test-DscProperty.ps1 +++ b/source/Public/Test-DscProperty.ps1 @@ -8,7 +8,7 @@ it is assigned a non-null value. .PARAMETER InputObject - Specifies the object that should be tested for existens of the specified + Specifies the object that should be tested for existence of the specified property. .PARAMETER Name From 1a54d286729090a5be3fc5855e1fc2ce993f69b5 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:24:09 +0100 Subject: [PATCH 07/13] Use arraylist for quick improvement --- source/Private/Test-DscPropertyState.ps1 | 4 +- source/Public/Compare-DscParameterState.ps1 | 102 ++++++++++-------- .../Public/Compare-ResourcePropertyState.ps1 | 2 +- source/Public/Find-Certificate.ps1 | 2 +- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/source/Private/Test-DscPropertyState.ps1 b/source/Private/Test-DscPropertyState.ps1 index aacfaf8..ff4d4dd 100644 --- a/source/Private/Test-DscPropertyState.ps1 +++ b/source/Private/Test-DscPropertyState.ps1 @@ -58,7 +58,7 @@ function Test-DscPropertyState New-InvalidOperationException -Message $errorMessage } - $propertyState = @() + $propertyState = [System.Collections.ArrayList]::new() <# It is a collection of CIM instances, then recursively call @@ -138,7 +138,7 @@ function Test-DscPropertyState } elseif ($Values.DesiredValue -is [Microsoft.Management.Infrastructure.CimInstance]) { - $propertyState = @() + $propertyState = [System.Collections.ArrayList]::new() <# It is a CIM instance, recursively call Test-DscPropertyState for each diff --git a/source/Public/Compare-DscParameterState.ps1 b/source/Public/Compare-DscParameterState.ps1 index f2ce244..a5fc351 100644 --- a/source/Public/Compare-DscParameterState.ps1 +++ b/source/Public/Compare-DscParameterState.ps1 @@ -184,8 +184,9 @@ function Compare-DscParameterState $IncludeValue ) - $returnValue = @() - #region ConvertCIm to Hashtable + $returnValue = [System.Collections.ArrayList]::new() + + #region ConvertCIM to Hashtable if ($CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance] -or $CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance[]]) { @@ -197,12 +198,15 @@ function Compare-DscParameterState { $DesiredValues = ConvertTo-HashTable -CimInstance $DesiredValues } - #endregion Endofconverion + #endregion EndOfConversion + #region CheckType of object - $types = 'System.Management.Automation.PSBoundParametersDictionary', - 'System.Collections.Hashtable', - 'Microsoft.Management.Infrastructure.CimInstance', + $types = @( + 'System.Management.Automation.PSBoundParametersDictionary' + 'System.Collections.Hashtable' + 'Microsoft.Management.Infrastructure.CimInstance' 'System.Collections.Specialized.OrderedDictionary' + ) if ($DesiredValues.GetType().FullName -notin $types) { @@ -217,7 +221,8 @@ function Compare-DscParameterState -Message ($script:localizedData.InvalidCurrentValuesError -f $CurrentValues.GetType().FullName) ` -ArgumentName 'CurrentValues' } - #endregion checktype + #endregion CheckType + #region check if CimInstance and not have properties in parameters invoke exception if ($DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance] -and -not $Properties) { @@ -226,6 +231,7 @@ function Compare-DscParameterState -ArgumentName Properties } #endregion check cim and properties + #Clean value if there are a common parameters provide from Test/Get-TargetResource parameter $desiredValuesClean = Remove-CommonParameter -Hashtable $DesiredValues #region generate keyList based on $Properties and $excludeProperties value @@ -240,16 +246,17 @@ function Compare-DscParameterState if ($ExcludeProperties) { - $keyList = $keyList | Where-Object -FilterScript { $_ -notin $ExcludeProperties } + $keyList = $keyList.Where({ $_ -notin $ExcludeProperties }) } #endregion + #region enumerate of each key in list foreach ($key in $keyList) { #generate default value $InDesiredStateTable = [ordered]@{ - Property = $key - InDesiredState = $true + Property = $key + InDesiredState = $true } $returnValue += $InDesiredStateTable #get value of each key @@ -259,8 +266,8 @@ function Compare-DscParameterState #Check if IncludeValue parameter is used. if ($IncludeValue) { - $InDesiredStateTable['ExpectedValue'] = $desiredValue - $InDesiredStateTable['ActualValue'] = $currentValue + $InDesiredStateTable['ExpectedValue'] = $desiredValue + $InDesiredStateTable['ActualValue'] = $currentValue } #region convert to hashtable if value of key is CimInstance @@ -274,8 +281,9 @@ function Compare-DscParameterState { $currentValue = ConvertTo-HashTable -CimInstance $currentValue } - #endregion converttohashtable - #region gettype of value to check if they are the same. + #endregion ConvertToHashtable + + #region GetType of value to check if they are the same. if ($null -ne $desiredValue) { $desiredType = $desiredValue.GetType() @@ -303,7 +311,8 @@ function Compare-DscParameterState $InDesiredStateTable['ActualType'] = $currentType #endregion - #region check if the desiredtype if a credential object. Only if the current type isn't unknown. + + #region check if the DesiredType if a credential object. Only if the current type isn't unknown. if ($currentType.Name -ne 'Unknown' -and $desiredType.Name -eq 'PSCredential') { # This is a credential object. Compare only the user name @@ -384,7 +393,7 @@ function Compare-DscParameterState } elseif (-not $currentValue) { - #If only currentvalue is empty, the configuration isn't compliant. + #If only CurrentValue is empty, the configuration isn't compliant. Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue) $InDesiredStateTable.InDesiredState = $false continue @@ -407,7 +416,7 @@ function Compare-DscParameterState $currentArrayValues = @($currentArrayValues | Sort-Object) } <# - for all object in collection, check their type.ConvertoString if they are script block. + for all object in collection, check their type.ConvertToString if they are script block. #> for ($i = 0; $i -lt $desiredArrayValues.Count; $i++) @@ -446,9 +455,9 @@ function Compare-DscParameterState } <# - Convert a scriptblock into a string as scriptblocks are not comparable - if currentvalue is scriptblock and if desired value is string, - we invoke the result of script block. Ifno, we convert to string. + Convert a scriptblock into a string as ScriptBlocks are not comparable + if CurrentValue is scriptblock and if desired value is string, + we invoke the result of script block. If no, we convert to string. if Desired value #> @@ -478,16 +487,17 @@ function Compare-DscParameterState } } - if (($desiredType -eq [System.Collections.Hashtable] -or $desiredType -eq [System.Collections.Specialized.OrderedDictionary]) -and ($currentType -eq [System.Collections.Hashtable]-or $currentType -eq [System.Collections.Specialized.OrderedDictionary])) + if (($desiredType -eq [System.Collections.Hashtable] -or $desiredType -eq [System.Collections.Specialized.OrderedDictionary]) -and ($currentType -eq [System.Collections.Hashtable] -or $currentType -eq [System.Collections.Specialized.OrderedDictionary])) { $param = @{} + $PSBoundParameters $param.CurrentValues = $currentArrayValues[$i] $param.DesiredValues = $desiredArrayValues[$i] - 'IncludeInDesiredState','IncludeValue','Properties','ReverseCheck' | ForEach-Object { - if ($param.ContainsKey($_)) + foreach ($key in 'IncludeInDesiredState', 'IncludeValue', 'Properties', 'ReverseCheck') + { + if ($param.ContainsKey($key)) { - $null = $param.Remove($_) + $null = $param.Remove($key) } } @@ -497,7 +507,7 @@ function Compare-DscParameterState } else { - Test-DscParameterState @param | Out-Null + $null = Test-DscParameterState @param } continue } @@ -516,23 +526,24 @@ function Compare-DscParameterState } } } - elseif (($desiredType -eq [System.Collections.Hashtable] -or $desiredType -eq [System.Collections.Specialized.OrderedDictionary]) -and ($currentType -eq [System.Collections.Hashtable]-or $currentType -eq [System.Collections.Specialized.OrderedDictionary])) + elseif (($desiredType -eq [System.Collections.Hashtable] -or $desiredType -eq [System.Collections.Specialized.OrderedDictionary]) -and ($currentType -eq [System.Collections.Hashtable] -or $currentType -eq [System.Collections.Specialized.OrderedDictionary])) { $param = @{} + $PSBoundParameters $param.CurrentValues = $currentValue $param.DesiredValues = $desiredValue - 'IncludeInDesiredState','IncludeValue','Properties','ReverseCheck' | ForEach-Object { - if ($param.ContainsKey($_)) + foreach ($key in 'IncludeInDesiredState', 'IncludeValue', 'Properties', 'ReverseCheck') + { + if ($param.ContainsKey($key)) { - $null = $param.Remove($_) + $null = $param.Remove($key) } } if ($InDesiredStateTable.InDesiredState) { <# - if desiredvalue is an empty hashtable and not currentvalue, it's not necessery to compare them, it's not compliant. + if Desired Value is an empty hashtable and not Current Value, it's not necessary to compare them, it's not compliant. See issue 65 https://github.com/dsccommunity/DscResource.Common/issues/65 #> if ($desiredValue.Keys.Count -eq 0 -and $currentValue.Keys.Count -ne 0) @@ -540,7 +551,8 @@ function Compare-DscParameterState Write-Verbose -Message ($script:localizedData.NoMatchKeyMessage -f $desiredType.FullName, $key, $($currentValue.Keys -join ', ')) $InDesiredStateTable.InDesiredState = $false } - else{ + else + { $InDesiredStateTable.InDesiredState = Test-DscParameterState @param } } @@ -552,7 +564,7 @@ function Compare-DscParameterState } else { - #Convert a scriptblock into a string as scriptblocks are not comparable + #Convert a scriptblock into a string as ScriptBlocks are not comparable $wasCurrentValue = $false if ($currentValue -is [scriptblock]) { @@ -611,27 +623,27 @@ function Compare-DscParameterState } } - # Remove in desired state value if IncludeDesirateState parameter is not use + # Remove in desired state value if IncludeDesiredState parameter is not use if (-not $IncludeInDesiredState) { - [array]$returnValue = $returnValue.where({$_.InDesiredState -eq $false}) + [array]$returnValue = $returnValue.Where({ $_.InDesiredState -eq $false }) } #change verbose message if ($IncludeInDesiredState.IsPresent) { $returnValue.ForEach({ - if ($_.InDesiredState) - { - $localizedString = $script:localizedData.PropertyInDesiredStateMessage - } - else - { - $localizedString = $script:localizedData.PropertyNotInDesiredStateMessage - } + if ($_.InDesiredState) + { + $localizedString = $script:localizedData.PropertyInDesiredStateMessage + } + else + { + $localizedString = $script:localizedData.PropertyNotInDesiredStateMessage + } - Write-Verbose -Message ($localizedString -f $_.Property) - }) + Write-Verbose -Message ($localizedString -f $_.Property) + }) } <# If Compare-DscParameterState is used in precedent step, don't need to convert it @@ -642,7 +654,7 @@ function Compare-DscParameterState { if ($_ -is [System.Collections.Hashtable]) { - [pscustomobject]$_ + [PSCustomObject]$_ } else { diff --git a/source/Public/Compare-ResourcePropertyState.ps1 b/source/Public/Compare-ResourcePropertyState.ps1 index 55e8176..c7f3431 100644 --- a/source/Public/Compare-ResourcePropertyState.ps1 +++ b/source/Public/Compare-ResourcePropertyState.ps1 @@ -203,7 +203,7 @@ function Compare-ResourcePropertyState } } - $compareTargetResourceStateReturnValue = @() + $compareTargetResourceStateReturnValue = [System.Collections.ArrayList]::new() foreach ($parameterName in $DesiredValues.Keys) { diff --git a/source/Public/Find-Certificate.ps1 b/source/Public/Find-Certificate.ps1 index c6f4a2a..0a06c67 100644 --- a/source/Public/Find-Certificate.ps1 +++ b/source/Public/Find-Certificate.ps1 @@ -131,7 +131,7 @@ function Find-Certificate } # if # Assemble the filter to use to select the certificate - $certFilters = @() + $certFilters = [System.Collections.ArrayList]::new() if ($PSBoundParameters.ContainsKey('Thumbprint')) { From f0b029a98d716962b2aacd0db77bb1561585722c Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:37:49 +0100 Subject: [PATCH 08/13] Add changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 075100f..ecbd9aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 for variable values, type comparisons, and internal diagnostics. - Comparison result still uses `Write-Verbose` to provide user-actionable information about parameter state differences. + - Use ArrayList and not fixed size array. + - Remove some ForEach-Object usage. - `Test-ModuleExist` - Changed module filtering messages from `Write-Verbose` to `Write-Debug` for internal implementation details. @@ -21,9 +23,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Changed operating system SKU diagnostic message from `Write-Verbose` to `Write-Debug`. - `Find-Certificate` - Changed certificate filter diagnostic message from `Write-Verbose` to `Write-Debug`. + - Use ArrayList and not fixed size array. - `Get-LocalizedDataForInvariantCulture` - Changed file processing message from `Write-Verbose` to `Write-Debug` for internal diagnostic information. +- `Clear-ZeroedEnumPropertyValue` + - Add before, end blocks. +- `Test-DscPropertyState` + - Use ArrayList and not fixed size array. +- `Assert-BoundParameter` + - Fix PSSA warning. +- `ConvertFrom-DscResourceInstance` + - Fix PSSA warning. +- `Get-DscProperty` + - Use ArrayList and not fixed size array. + - Fix PSSA warning. +- `Remove-CommonParameter` + - Remove use of `Where-Object` and `ForEach-Object`. ## [0.24.1] - 2025-08-27 From 43dee490b91c42868865e7f1d958b68aa333c897 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:48:30 +0100 Subject: [PATCH 09/13] Remove extra newlines --- source/Private/Clear-ZeroedEnumPropertyValue.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/Private/Clear-ZeroedEnumPropertyValue.ps1 b/source/Private/Clear-ZeroedEnumPropertyValue.ps1 index 58d4eb8..95a9d63 100644 --- a/source/Private/Clear-ZeroedEnumPropertyValue.ps1 +++ b/source/Private/Clear-ZeroedEnumPropertyValue.ps1 @@ -34,7 +34,6 @@ function Clear-ZeroedEnumPropertyValue process { - foreach ($property in $InputObject.Keys) { $value = $InputObject.$property @@ -45,7 +44,6 @@ function Clear-ZeroedEnumPropertyValue $result.$property = $value } - } end From d7bb0db4eafac1a8d5c4a2000bb4056230b25757 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:48:49 +0100 Subject: [PATCH 10/13] Use HashSet --- source/Public/Remove-CommonParameter.ps1 | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/source/Public/Remove-CommonParameter.ps1 b/source/Public/Remove-CommonParameter.ps1 index 75530a7..f7c8496 100644 --- a/source/Public/Remove-CommonParameter.ps1 +++ b/source/Public/Remove-CommonParameter.ps1 @@ -19,11 +19,6 @@ #> function Remove-CommonParameter { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSUseShouldProcessForStateChangingFunctions', - '', - Justification = 'ShouldProcess is not supported in DSC resources.' - )] [OutputType([System.Collections.Hashtable])] [CmdletBinding()] param @@ -35,16 +30,19 @@ function Remove-CommonParameter $inputClone = $Hashtable.Clone() - $commonParameters = @( - [System.Management.Automation.PSCmdlet]::CommonParameters - [System.Management.Automation.PSCmdlet]::OptionalCommonParameters - ) + $commonParameters = [System.Collections.Generic.HashSet[System.String]]::new( + [System.String[]]( + [System.Management.Automation.PSCmdlet]::CommonParameters + + [System.Management.Automation.PSCmdlet]::OptionalCommonParameters + ), + [System.StringComparer]::OrdinalIgnoreCase + ) foreach ($key in $Hashtable.Keys) { - if ($key -in $commonParameters) + if ($commonParameters.Contains($key)) { - $inputClone.Remove($key) + $null = $inputClone.Remove($key) } } From 09e58bf6b0606032a0a300fea5189c4c3432cdb2 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:48:56 +0100 Subject: [PATCH 11/13] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecbd9aa..bd7174f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Changed file processing message from `Write-Verbose` to `Write-Debug` for internal diagnostic information. - `Clear-ZeroedEnumPropertyValue` - - Add before, end blocks. + - Add begin, end blocks. - `Test-DscPropertyState` - Use ArrayList and not fixed size array. - `Assert-BoundParameter` From 7b2fa3ba1b44ef9b1a8bcdc101450f177243119d Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:04:38 +0100 Subject: [PATCH 12/13] Add PSSA Suppression back --- source/Public/Remove-CommonParameter.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/Public/Remove-CommonParameter.ps1 b/source/Public/Remove-CommonParameter.ps1 index f7c8496..e65540d 100644 --- a/source/Public/Remove-CommonParameter.ps1 +++ b/source/Public/Remove-CommonParameter.ps1 @@ -19,6 +19,11 @@ #> function Remove-CommonParameter { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', + '', + Justification = 'ShouldProcess is not supported in DSC resources.' + )] [OutputType([System.Collections.Hashtable])] [CmdletBinding()] param From cb40e7f24b7f9a791c2d22ff5eba56fcd5440ec9 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:16:14 +0100 Subject: [PATCH 13/13] Remove single use variables --- source/Private/Test-DscPropertyState.ps1 | 64 +++++++++--------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/source/Private/Test-DscPropertyState.ps1 b/source/Private/Test-DscPropertyState.ps1 index ff4d4dd..446fa06 100644 --- a/source/Private/Test-DscPropertyState.ps1 +++ b/source/Private/Test-DscPropertyState.ps1 @@ -48,14 +48,12 @@ function Test-DscPropertyState } elseif ( $Values.DesiredValue -is [Microsoft.Management.Infrastructure.CimInstance[]] ` - -or $Values.DesiredValue -is [System.Array] -and $Values.DesiredValue[0] -is [Microsoft.Management.Infrastructure.CimInstance] + -or $Values.DesiredValue -is [System.Array] -and $Values.DesiredValue[0] -is [Microsoft.Management.Infrastructure.CimInstance] ) { if (-not $Values.ContainsKey('KeyProperties')) { - $errorMessage = $script:localizedData.KeyPropertiesMissing - - New-InvalidOperationException -Message $errorMessage + New-InvalidOperationException -Message $script:localizedData.KeyPropertiesMissing } $propertyState = [System.Collections.ArrayList]::new() @@ -80,23 +78,20 @@ function Test-DscPropertyState if ($currentCimInstance.Count -gt 1) { - $errorMessage = $script:localizedData.TooManyCimInstances - - New-InvalidOperationException -Message $errorMessage + New-InvalidOperationException -Message $script:localizedData.TooManyCimInstances } if ($currentCimInstance) { - $keyCimInstanceProperties = $currentCimInstance.CimInstanceProperties | - Where-Object -FilterScript { + $keyCimInstanceProperties = $currentCimInstance.CimInstanceProperties.Where({ $_.Name -in $Values.KeyProperties - } + }) <# For each key property build a string representation of the property name and its value. #> - $keyPropertyValues = $keyCimInstanceProperties.ForEach({'{0}="{1}"' -f $_.Name, ($_.Value -join ',')}) + $keyPropertyValues = $keyCimInstanceProperties.ForEach({ '{0}="{1}"' -f $_.Name, ($_.Value -join ',') }) Write-Debug -Message ( $script:localizedData.TestingCimInstance -f @( @@ -107,16 +102,15 @@ function Test-DscPropertyState } else { - $keyCimInstanceProperties = $desiredCimInstance.CimInstanceProperties | - Where-Object -FilterScript { + $keyCimInstanceProperties = $desiredCimInstance.CimInstanceProperties.Where({ $_.Name -in $Values.KeyProperties - } + }) <# For each key property build a string representation of the property name and its value. #> - $keyPropertyValues = $keyCimInstanceProperties.ForEach({'{0}="{1}"' -f $_.Name, ($_.Value -join ',')}) + $keyPropertyValues = $keyCimInstanceProperties.ForEach({ '{0}="{1}"' -f $_.Name, ($_.Value -join ',') }) Write-Debug -Message ( $script:localizedData.MissingCimInstance -f @( @@ -186,21 +180,21 @@ function Test-DscPropertyState { Write-Debug -Message $script:localizedData.ArrayDoesNotMatch - $arrayCompare | - ForEach-Object -Process { - if ($_.SideIndicator -eq '=>') - { - Write-Debug -Message ( - $script:localizedData.ArrayValueIsAbsent -f $_.InputObject - ) - } - else - { - Write-Debug -Message ( - $script:localizedData.ArrayValueIsPresent -f $_.InputObject - ) - } + foreach ($item in $arrayCompare) + { + if ($item.SideIndicator -eq '=>') + { + Write-Debug -Message ( + $script:localizedData.ArrayValueIsAbsent -f $item.InputObject + ) } + else + { + Write-Debug -Message ( + $script:localizedData.ArrayValueIsPresent -f $item.InputObject + ) + } + } $returnValue = $false } @@ -215,17 +209,7 @@ function Test-DscPropertyState $returnValue = $false - $supportedTypes = @( - 'String' - 'Int32' - 'UInt32' - 'Int16' - 'UInt16' - 'Single' - 'Boolean' - ) - - if ($desiredType.Name -notin $supportedTypes) + if ($desiredType.Name -notin 'String', 'Int32', 'UInt32', 'Int16', 'UInt16', 'Single', 'Boolean') { Write-Warning -Message ($script:localizedData.UnableToCompareType -f $desiredType.Name) }