Get-PSSession and Invoke-Command Pipeline Question

This topic contains 1 reply, has 2 voices, and was last updated by  Don Jones 2 weeks, 3 days ago.

  • Author
    Posts
  • #101659

    James
    Participant

    I trying to learn PowerShell core 6.0, and today i met issue i can't understand.

    Get-PSSession | Write-Output -InputObject {$_}

    This work fine. I can pass Get-PSSession result to Write-Output by using {$_}.

    Get-PSSession | Invoke-Command -Session {$_} -ScriptBlock {ls}

    This one is not working. With error:"Cannot bind parameter 'Session'. Cannot convert the "$_" value of type "System.Management.Automation.ScriptBlock" to type "System.Management.Automation.Runspaces.PSSession""

    But below one work fine after i add foreach and remove "{}" from "$_"

     Get-PSSession | foreach{ Invoke-Command -Session $_ -ScriptBlock {ls}}

    Can anyone help me understand this?

  • #101662

    Don Jones
    Keymaster

    So for the benefit of those coming later, just know that these are exactly the same:

    Get-PSSession | Write-Output -InputObject {$_}
    Get-PSSession | Write-Output
    Get-PSSession
    

    E.e., Write-Output is unnecessary. But I get why you're using it in this example, and it plays into why it's unnecessary. It's important to know that $_ isn't globally defined in PowerShell; it doesn't _always_ mean 'the thing that came in from the pipeline'. $_ only works in specific areas where PowerShell has been programmed to look for it.

    In the above example, the -InputObject parameter of Write-Output is coded to bind objects of type [object] from the pipeline. As _everything_ inherits from System.Object, that means -InputObject will accept literally anything. That's why the above works.

    Get-PSSession | Invoke-Command -Session {$_} -ScriptBlock {ls}
    

    The -Session parameter _doesn't accept pipeline input_, as described in the command's documentation. So you're trying to "work around" that, I think.

    By enclosing $_ in {}, you've not "executed" $_ to see if it contains anything; you've instead made a script block, which cannot be coerced into being a session. Thus, the error you got.

    Your first example "works," but it mainly does so by accident; Write-Object isn't really intended to be used that way, and you've just stumbled across a situation where it does.

    The "correct" workaround (one of many) might be:

    Invoke-Command -Session (Get-PSSession) -ScriptBlock {ls}
    

    In your last example, ForEach-Object is in fact one of the magic places where $_ works. By removing {}, you've stopped creating a script block and instead are allowing ForEach-Object to treat $_ as it normally would – to represent the piped-in object.

You must be logged in to reply to this topic.