PoshRSJob icon indicating copy to clipboard operation
PoshRSJob copied to clipboard

-ArgumentList argument count incorrect, causing "shift" of first parameter to $_

Open slickmonkey opened this issue 7 years ago • 4 comments

Do you want to request a feature or report a bug? Bug What is the current behavior? Start-RSJob incorrectly counts the parameters in the -ArgumentList, altering its behavior loading parameter values in the Runspace job and setting $_ (pipeline) to the first value in the -ArgumentList parameter. (I've seen previous, similar posts for problems with -ArgumentList, but I'm identifying the specific line I think is the problem, below) Note the DEBUG: ArgumentCount: X | SBParamCount: Y | IsPipeline: True in the output(s) given below

The bug is on line 285 of Start-RSJob: $ArgumentCount = If (-not $ArgumentList -or ($SingleArgument -eq 0)) { # Empty array, or, 0 count

The $(SingleArgument -eq 0) resolves to TRUE even when $SingleArgument is False, because PowerShell is treating False == 0. For example:

PS C:\> if ($false -eq 0) { Write-Host "False is apparently zero, too" }
False is apparently zero, too

For the time being, I have fixed this locally with: $ArgumentCount = If (-not $ArgumentList -or ($SingleArgument -and $SingleArgument -eq 0)) { # Empty array, or, 0 count

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem Example of current failure:

PS C:\Users\me\Documents\WindowsPowerShell> $scriptTemplate = @'
Param (
    [object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";
'@
$scriptBlock = [System.Management.Automation.ScriptBlock]::Create($scriptTemplate);

Start-RSJob -ScriptBlock $scriptBlock -ArgumentList $param1,$param2 -Verbose -Debug

DEBUG: [BEGIN]
VERBOSE: Displaying PSBoundParameters
VERBOSE: [ScriptBlock, Param (
    [object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";]
VERBOSE: [ArgumentList, System.Object[]]
VERBOSE: [Verbose, True]
VERBOSE: [Debug, True]
VERBOSE: Creating default Job Name
DEBUG: 2 argument/s passed via -ArgumentList
DEBUG: [PROCESS]
DEBUG: [END]
DEBUG: ArgumentCount: 0 | SBParamCount: 2 | IsPipeline: True
VERBOSE: Will use $_ in Param() Block
VERBOSE: PowerShell Version: 5
DEBUG: Using AST with PowerShell V3+
DEBUG: ScriptBlock: Param (
    $_,
[object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";
VERBOSE: Creating new runspacepool <545b7dab-2bc6-4a74-9436-c7a71431bb16>
DEBUG: No InputObject
VERBOSE: Incrementing job ID
VERBOSE: Adding Argument: FirstParam <System.String>
VERBOSE: Adding Argument: SecondParam <System.String>

Id       Name                 State           HasMoreData  HasErrors    Command                                 
--       ----                 -----           -----------  ---------    -------                                 
1        Job1                 Completed       True         False        Param (...                              

PS C:\Users\me\Documents\WindowsPowerShell> Get-RSJob | Receive-RSJob
Piped object: FirstParam
Param1: SecondParam
Param2: 

PS C:\Users\me\Documents\WindowsPowerShell> 

What is the expected behavior? Same example, with fix given above in place (line 285):

PS C:\Users\me\Documents\WindowsPowerShell> $scriptTemplate = @'
Param (
    [object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";
'@
$scriptBlock = [System.Management.Automation.ScriptBlock]::Create($scriptTemplate);

Start-RSJob -ScriptBlock $scriptBlock -ArgumentList $param1,$param2 -Verbose -Debug

DEBUG: [BEGIN]
VERBOSE: Displaying PSBoundParameters
VERBOSE: [ScriptBlock, Param (
    [object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";]
VERBOSE: [ArgumentList, System.Object[]]
VERBOSE: [Verbose, True]
VERBOSE: [Debug, True]
VERBOSE: Creating default Job Name
DEBUG: 2 argument/s passed via -ArgumentList
DEBUG: [PROCESS]
DEBUG: [END]
DEBUG: ArgumentCount: 2 | SBParamCount: 2 | IsPipeline: True
VERBOSE: PowerShell Version: 5
DEBUG: Using AST with PowerShell V3+
DEBUG: ScriptBlock: Param (
    [object] $p1,
    [string] $p2
)
Write-Output "Piped object: $_";
Write-Output "Param1: $p1";
Write-Output "Param2: $p2";
VERBOSE: Creating new runspacepool <43abebe4-2265-439a-9eea-a1b2a5d37056>
DEBUG: No InputObject
VERBOSE: Incrementing job ID
VERBOSE: Adding Argument: FirstParam <System.String>
VERBOSE: Adding Argument: SecondParam <System.String>

Id       Name                 State           HasMoreData  HasErrors    Command                                 
--       ----                 -----           -----------  ---------    -------                                 
1        Job1                 Completed       True         False        Param (...                              


PS C:\Users\me\Documents\WindowsPowerShell> Get-RSJob | Receive-RSJob
Piped object: 
Param1: FirstParam
Param2: SecondParam

Which versions of Powershell and which OS are affected by this issue? Did this work in previous versions of our scripts?

PS C:\Users\alandye\Documents\WindowsPowerShell> $PSVersionTable
Name                           Value                                                                                   
----                           -----                                                                                   
PSVersion                      5.1.15063.0                                                                             
PSEdition                      Desktop                                                                                 
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                 
BuildVersion                   10.0.15063.0                                                                            
CLRVersion                     4.0.30319.42000                                                                         
WSManStackVersion              3.0                                                                                     
PSRemotingProtocolVersion      2.3                                                                                     
SerializationVersion           1.1.0.1

PoshRSJob module version is 1.7.3.9

Don't know if this previously (ever) worked.

Please provide a code example showing the issue, if applicable:

PS C:\Users\me\Documents\WindowsPowerShell> $scriptTemplate = @' Param ( [object] $p1, [string] $p2 ) Write-Output "Piped object: $_"; Write-Output "Param1: $p1"; Write-Output "Param2: $p2"; '@ $scriptBlock = [System.Management.Automation.ScriptBlock]::Create($scriptTemplate);

Start-RSJob -ScriptBlock $scriptBlock -ArgumentList $param1,$param2 -Verbose -Debug

PS C:\Users\me\Documents\WindowsPowerShell> Get-RSJob | Receive-RSJob

slickmonkey avatar May 03 '17 23:05 slickmonkey

I am still seeing this issue in version 1.7.3.11. The suggested fix in the original posting works. Any chance this will fix (or some other version of this fix) will be incorporated in a future version?

nszhang avatar Sep 11 '17 22:09 nszhang

I'm ready to make PR which should fix it. Please test my fork before...

MVKozlov avatar Sep 12 '17 06:09 MVKozlov

Should say, this is feature :) The way it works not clearly documented: If you want to read large text, you can try :) https://github.com/MVKozlov/PoshRSJob/wiki/NewParam-branch-changes short version: If scriptblock.param.count -ne 1 or if scriptblock.param.count -eq argumentlist.count -and pipeline.count -gt 0 pipeline value inserted as $_ in scriptblock argumentlist.count = real arguments count + pipeline and now there is a bug, when $_ inserted when param.count -eq argumentlist.count even there is no pipeline input

MVKozlov avatar Sep 12 '17 06:09 MVKozlov

Thanks for the quick response. I tested the code in your fork and I can confirm that the -Argumentlist parameter bug is fixed.

nszhang avatar Sep 12 '17 17:09 nszhang