Search code examples
powershellstart-job

Cannot bind parameter to argument 'command' because it is null. Powershell


I had a function similar to below code. It receives command and the command arguments. I had to run this command in background and collect the output. But that last statement is bugging me with this error

Error:

Cannot bind argument to parameter 'Command' because it is null.
+ CategoryInfo          : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpre
ssionCommand
+ PSComputerName        : localhost

Code:

$cmd = 'Get-content'
$Arg = 'path to file'
$sb = "$cmd $Arg -ErrorVariable e -ErrorAction Stop"
invoke-Expression $sb #This printsoutput
$job = Start-job -ScriptBlock {Invoke-Expression $sb}
wait-job -id $job.Id
$job | Receive-job #this should print output but throwing error

I am pretty sure last line is the one throwing the error.


Solution

  • The issue here is that you are not actually giving Invoke-Expression a command.

    Whenever you create a new context ( in this case, a job ) you loose your access to the parent session's environment. In your case $sb is currently null.

    The way that you manage this is to pass the values as arguments via the -ArgumentList parameter of Start-Job:

    start-job -ScriptBlock {} -ArgumentList
    

    In order to facilitate handing $sb to the ScriptBlock you would do this:

    $sb = "$cmd $Arg -ErrorVariable e -ErrorAction Stop"
    $job = start-job -ScriptBlock { Param([string]$sb)
        Invoke-Expression $sb
    } -ArgumentList $sb
    

    This can be confusing so this is the same code written with more friendly names:

    $OuterSB = "$cmd $Arg -ErrorVariable e -ErrorAction Stop"
    $job = start-job -ScriptBlock { Param([string]$InnerSB)
        Invoke-Expression $InnerSB
    } -ArgumentList $OuterSB