Skip to content

Commit d04c039

Browse files
bergmeisterChristoph Bergmeister
and
Christoph Bergmeister
authored
UseCorrectCasing: Do not use CommandInfoCache when CommandInfoParameters property throws due to runspace affinity problem of PowerShell engine (#1523)
* UseCorrectCasing: Do not use CommandInfoCache because Parameters property has runspace affinity problems * Catch exception and only bypass cache then * Add test Co-authored-by: Christoph Bergmeister <christoph.bergmeister@bjss.com>
1 parent 562b8c3 commit d04c039

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

Engine/CommandInfoCache.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,20 @@ protected virtual void Dispose(bool disposing)
5757
/// </summary>
5858
/// <param name="commandName">Name of the command to get a commandinfo object for.</param>
5959
/// <param name="commandTypes">What types of command are needed. If omitted, all types are retrieved.</param>
60+
/// <param name="bypassCache">When needed due to runspace affinity problems of some PowerShell objects.</param>
6061
/// <returns></returns>
61-
public CommandInfo GetCommandInfo(string commandName, CommandTypes? commandTypes = null)
62+
public CommandInfo GetCommandInfo(string commandName, CommandTypes? commandTypes = null, bool bypassCache = false)
6263
{
6364
if (string.IsNullOrWhiteSpace(commandName))
6465
{
6566
return null;
6667
}
6768

6869
var key = new CommandLookupKey(commandName, commandTypes);
70+
if (bypassCache)
71+
{
72+
return GetCommandInfoInternal(commandName, commandTypes);
73+
}
6974
// Atomically either use PowerShell to query a command info object, or fetch it from the cache
7075
return _commandInfoCache.GetOrAdd(key, new Lazy<CommandInfo>(() => GetCommandInfoInternal(commandName, commandTypes))).Value;
7176
}

Engine/Helper.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,11 @@ public bool PositionalParameterUsed(CommandAst cmdAst, bool moreThanTwoPositiona
673673
/// </summary>
674674
/// <param name="name"></param>
675675
/// <param name="commandType"></param>
676+
/// <param name="bypassCache"></param>
676677
/// <returns></returns>
677-
public CommandInfo GetCommandInfo(string name, CommandTypes? commandType = null)
678+
public CommandInfo GetCommandInfo(string name, CommandTypes? commandType = null, bool bypassCache = false)
678679
{
679-
return CommandInfoCache.GetCommandInfo(name, commandTypes: commandType);
680+
return CommandInfoCache.GetCommandInfo(name, commandTypes: commandType, bypassCache: bypassCache);
680681
}
681682

682683
/// <summary>

Rules/UseCorrectCasing.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,19 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
6969

7070
var commandParameterAsts = commandAst.FindAll(
7171
testAst => testAst is CommandParameterAst, true).Cast<CommandParameterAst>();
72-
var availableParameters = commandInfo.Parameters;
72+
Dictionary<string, ParameterMetadata> availableParameters;
73+
try
74+
{
75+
availableParameters = commandInfo.Parameters;
76+
}
77+
// It's a known issue that objects from PowerShell can have a runspace affinity,
78+
// therefore if that happens, we query a fresh object instead of using the cache.
79+
// https://github.com/PowerShell/PowerShell/issues/4003
80+
catch (InvalidOperationException)
81+
{
82+
commandInfo = Helper.Instance.GetCommandInfo(commandName, bypassCache: true);
83+
availableParameters = commandInfo.Parameters;
84+
}
7385
foreach (var commandParameterAst in commandParameterAsts)
7486
{
7587
var parameterName = commandParameterAst.ParameterName;

Tests/Rules/UseCorrectCasing.tests.ps1

+9
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,13 @@ Describe "UseCorrectCasing" {
7373
Invoke-Formatter 'Get-Process -NonExistingParameterName' -ErrorAction Stop
7474
}
7575

76+
It "Does not throw when correcting certain cmdlets (issue 1516)" {
77+
$scriptDefinition = 'Get-Content;Test-Path;Get-ChildItem;Get-Content;Test-Path;Get-ChildItem'
78+
$settings = @{ 'Rules' = @{ 'PSUseCorrectCasing' = @{ 'Enable' = $true } } }
79+
{
80+
1..100 |
81+
ForEach-Object { $null = Invoke-ScriptAnalyzer -ScriptDefinition $scriptDefinition -Settings $settings -ErrorAction Stop }
82+
} |
83+
Should -Not -Throw
84+
}
7685
}

0 commit comments

Comments
 (0)