Psscriptanalyzer: The rule 'UseUsingScopeModifierInNewRunspaces' throw an ArgumentException

Created on 12 May 2020  Â·  5Comments  Â·  Source: PowerShell/PSScriptAnalyzer

Steps to reproduce

$s=@'
function Get-One{

    Invoke-Command -Session $sourceRemoteSession -ScriptBlock {
        if($null -eq (Get-PSProvider CMSite -ea Ignore)){
            $sccmModule = ("{0}\ConfigurationManager.psd1" -f (Split-Path $env:SMS_ADMIN_UI_PATH -Parent))
            Import-Module "$sccmModule" -Global
        }
    }
    return $importState
}

function Get-Two{

    Invoke-Command -Session $sourceRemoteSession -ScriptBlock {
        if($null -eq (Get-PSProvider CMSite -ea Ignore)){
            $sccmModule = ("{0}\ConfigurationManager.psd1" -f (Split-Path $env:SMS_ADMIN_UI_PATH -Parent))
            Import-Module "$sccmModule" -Global
        }
    }
    return $importState
}


'@
Invoke-ScriptAnalyzer -ScriptDefinition $s

Expected behavior

No error

Actual behavior

Invoke-ScriptAnalyzer : Un élément avec la même clé a déjà été ajouté. 
(An item with the same key has already been added)
Au caractère Ligne:1 : 1
 + Invoke-ScriptAnalyzer -ScriptDefinition $s
 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : InvalidOperation : (:) [Invoke-ScriptAnalyzer], ArgumentException
     + FullyQualifiedErrorId : RULE_ERROR,Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands.InvokeScriptAnalyzerCommand

If an unexpected error was thrown then please report the full error details using e.g. $error[0] | Select-Object *

writeErrorStream      : True
PSMessageDetails      :
Exception             : System.ArgumentException: Un élément avec la même clé a déjà été ajouté.
                           à System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
                           à System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
                           à Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseUsingScopeModifierInNewRunspac
                        es.SyntaxCompatibilityVisitor.AddAssignedVarsToSession(String sessionName,
                        IReadOnlyDictionary`2 variablesToAdd)
                           à Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseUsingScopeModifierInNewRunspac
                        es.SyntaxCompatibilityVisitor.VisitScriptBlockExpression(ScriptBlockExpressionAst
                        scriptBlockExpressionAst)
                           à System.Management.Automation.Language.ScriptBlockExpressionAst.InternalVisit(AstVisitor
                        visitor)
                           à System.Management.Automation.Language.CommandAst.InternalVisit(AstVisitor visitor)
                           à System.Management.Automation.Language.PipelineAst.InternalVisit(AstVisitor visitor)
                           à System.Management.Automation.Language.StatementBlockAst.InternalVisit(AstVisitor visitor,
                        ReadOnlyCollection`1 traps, ReadOnlyCollection`1 statements, AstVisitAction action)
                           à System.Management.Automation.Language.NamedBlockAst.InternalVisit(AstVisitor visitor)
                           à System.Management.Automation.Language.ScriptBlockAst.InternalVisit(AstVisitor visitor)
                           à System.Management.Automation.Language.FunctionDefinitionAst.InternalVisit(AstVisitor
                        visitor)
                           à System.Management.Automation.Language.StatementBlockAst.InternalVisit(AstVisitor visitor,
                        ReadOnlyCollection`1 traps, ReadOnlyCollection`1 statements, AstVisitAction action)
                           à System.Management.Automation.Language.NamedBlockAst.InternalVisit(AstVisitor visitor)
                           à System.Management.Automation.Language.ScriptBlockAst.InternalVisit(AstVisitor visitor)
                           à Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseUsingScopeModifierInNewRunspac
                        es.AnalyzeScript(Ast ast, String fileName)
                           à Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer.<>c__DisplayClass83_1.<AnalyzeS
                        yntaxTree>b__2()
TargetObject          :
CategoryInfo          : InvalidOperation : (:) [Invoke-ScriptAnalyzer], ArgumentException
FullyQualifiedErrorId : RULE_ERROR,Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands.InvokeScriptAnalyzerCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : à <ScriptBlock>, <Aucun fichier> : ligne 1
PipelineIterationInfo : {0, 1}

Environment data

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.18362.752
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.18362.752}
BuildVersion                   10.0.18362.752
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

> (Get-Module -ListAvailable PSScriptAnalyzer).Version | ForEach-Object { $_.ToString() }

1.19.0
1.18.3
1.18.1
1.18.0
1.17.1

The presence of the $sccmModule variable inside the two scriptblock causes the exception.
If we rename the first variable occurence to $sccmModuleOne there are no more exceptions.

Once again we do not know where the error took place. In the file 'xyz', but for which line?
In the error report, we do not know which line triggered the error, yet the analysis engine knows it.

Area - Rules Issue - Bug

All 5 comments

I can confirm. cc @Jawz84

The exception is originating from here:
https://github.com/PowerShell/PSScriptAnalyzer/blob/0bdcc328d54440125fcf4b116b437ab6410ff992/Rules/UseUsingScopeModifierInNewRunspaces.cs#L390
_varsDeclaredPerSession[sessionName] already contains the key sccmModule (with value $sccmModule)
A simple fix seems to be

                    if (!_varsDeclaredPerSession[sessionName].ContainsKey(item.Key))
                    {
                        _varsDeclaredPerSession[sessionName].Add(item.Key, item.Value);
                    }

@Jawz84 As far as I see the _varsDeclaredPerSession is only used once, when it is passed to GetAssignedVarsInSession and only the key is used but not value, thefore on an unrelated note it seems we could simplify _varsDeclaredPerSession to be Dictionary<string, HashSet<string> instead of Dictionary<string, Dictionary<string, VariableExpressionAst>>?

Thank you for attending to this and notifying me. I can't help at this time. I am in the middle of refurbishing my new house where we will be moving to in a few weeks.

No worries, it's just an FYI, I have a fix for it already in #1493

Was this page helpful?
0 / 5 - 0 ratings