What am I doing wrong?

This topic contains 3 replies, has 2 voices, and was last updated by  Dave Wyatt 4 years, 9 months ago.

  • Author
  • #10212


    Code below do not work over remoting but works fine on console. No errors are thrown but nothing being on remote server. I suspect it has something to do with pipeline not working correctly on remote session and not passing "name" parameter to Restart-WebApppool

    PS C:\Users\gsuvalian\desktop> Invoke-Command server {import-module WebAdministration; gci IIS:\\apppools | % Restart-WebAppPool } -cred $cred

    Code below works though

    PS C:\Users\gsuvalian\desktop> Invoke-Command server {import-module WebAdministration; gci IIS:\\apppools | % {Restart-WebAppPool $_.name} } -cred $cred

    Directly on remote console code below works as well

    $gci IIS:\\apppools | % Restart-WebAppPool

    On a separate note why code above works but not code below

    $gci IIS:\\apppools | % {Restart-WebAppPool}

  • #10217

    Dave Wyatt

    % is an alias for ForEach-Object. I haven't used these IIS-related commands before, but you may not need ForEach-Object at all. Try this (both in remoting and locally):

    gci IIS:\apppools | Restart-WebAppPool
    Invoke-Command server {import-module WebAdministration; gci IIS:\apppools | Restart-WebAppPool } -cred $cred

    If you do use ForEach-Object, then you need to do something with "$_" inside your script block, such as the gci IIS:\\apppools | % {Restart-WebAppPool $_.name} part of your second example.

  • #10218


    Interesting, removing "%,Foreach-object" does work in both cases (remotely and on console).
    Wondering what is going on in background. So powershell when piping any collection to another cmdlet automatically assumes that you want to iterate through collection? It might be good that Powershell is dumbed down to this level but that's really not very intuitive (at least for me).
    Why "Foreach-object" refuses to work also a mistery.

  • #10221

    Dave Wyatt

    You really only need ForEach-Object if you're doing something more complex, or if the command you want to pipe input to does not support pipeline input. Restart-WebAppPool does support piping the -Name argument by property name, and the objects output by your Get-ChildItem command have a Name property that is exactly what you needed. The end result of these two commands are identical (though the ForEach-Object version will not execute as fast):

    gci IIS:\apppools | Restart-WebAppPool
    gci IIS:\apppools | ForEach-Object { Restart-WebAppPool -Name $_.Name }

    There's technically no "collection" in either of those commands. The pipeline works by streaming one object at a time, and at no point are the entire results of Get-ChildItem saved in a collection. However, PowerShell does do some behind the scenes work when it comes to actual collections and the pipeline. For example:

    # set up our array
    $directories = @('C:\', 'C:\Windows','C:\Program Files')
    # Pipe the array to a command
    $directories | Get-ChildItem

    In this case, PowerShell isn't sending the array object itself to Get-ChildItem; it automatically sends the objects contained in the array, one at a time.

    There's a lot of information on this topic in the about_Pipelines help file.

You must be logged in to reply to this topic.