Piping Results from One PowerShell Cmdlet to Another

Piping Results from One PowerShell Cmdlet to Another

  • Comments 1
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about piping the results from one cmdlet to another.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a problem. When I pipe information from one Windows PowerShell cmdlet to anther (for example, when I use Get-Process and pipe it to Stop-Process ), sometimes it works, and sometimes it does not. This is not great. What is the deal? Can you help?

—LR

Hey, Scripting Guy! Answer Hello LR,

Microsoft Scripting Guy, Ed Wilson, is here. The nice thing about a hurricane is when it is gone. In Charlotte, we got some pretty heavy rain as a result of Hurricane Arthur, but nothing serious. Now we are enjoying the cool weather that followed that event. It seems like autumn outside.

LR, using the Windows PowerShell pipeline is not really like a hurricane, but sometimes it seems unpredictable. Therefore, things can appear to go around in circles. The key to knowing what is going on is understanding parameter sets.

For example, if I use Start-Process, I can easily start a new process. I can then use Get-Process to retrieve that process. This is shown here:

PS C:\> Start-Process notepad

PS C:\> get-Process notepad

 

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

     84       8     1508       8112   110     0.08   5412 notepad

It would seem to make sense that I can now pipe the results to the Stop-Process cmdlet and stop the process. But if I do this, I get the following error message:

PS C:\> get-Process notepad | Stop-Process notepad

Stop-Process : Cannot bind parameter 'InputObject'. Cannot convert the "notepad" value

of type "System.String" to type "System.Diagnostics.Process".

At line:1 char:36

+ get-Process notepad | Stop-Process notepad

+                                    ~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Stop-Process], ParameterBindingException

    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Comman

   ds.StopProcessCommand

The key is to realize this is not a “bogus error.” Rather, there is significant information here. It tells me that the cmdlet tries to bind the parameter InputObject, but that it does not work because “notepad” is a string and not a process object.

Three parameter sets

The Stop-Process cmdlet accepts the following three parameter sets:

PS C:\> Get-Command Stop-Process -Syntax

Stop-Process [-Id] <int[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]

 

Stop-Process -Name <string[]> [-PassThru] [-Force] [-WhatIf] [-Confirm]

[<CommonParameters>]

 

Stop-Process [-InputObject] <Process[]> [-PassThru] [-Force] [-WhatIf] [-Confirm]

[<CommonParameters>]

The default parameter set is ID, which accepts an integer in the first position. To find this information about parameter sets, use the Get-Command cmdlet and pipe the output to Select-Object while expanding the ParameterSets parameter.

Here is a sample of the output for the first parameter (ID). The output shows that ID is the default parameter set, and that ID appears in the first position and is mandatory. It also tells us that this parameter does not accept a value from the pipeline.

PS C:\> Get-Command Stop-Process | select -expand parametersets

 

Parameter Set Name: Id

Is default parameter set: True

 

  Parameter Name: Id

    ParameterType = System.Int32[]

    Position = 0

    IsMandatory = True

    IsDynamic = False

    HelpMessage =

    ValueFromPipeline = False

    ValueFromPipelineByPropertyName = True

    ValueFromRemainingArguments = False

    Aliases = {}

    Attributes =

      System.Management.Automation.ParameterAttribute

What about the Name parameter? Well, there is a Name parameter set. It is not the default parameter set, and it also does not accept a value from the pipeline. This is shown here:

Parameter Set Name: Name

Is default parameter set: False

 

  Parameter Name: Name

    ParameterType = System.String[]

    Position = -2147483648

    IsMandatory = True

    IsDynamic = False

    HelpMessage =

    ValueFromPipeline = False

    ValueFromPipelineByPropertyName = True

    ValueFromRemainingArguments = False

    Aliases = {ProcessName}

    Attributes =

      System.Management.Automation.AliasAttribute

      System.Management.Automation.ParameterAttribute

So, when I try to tell the Stop-Process cmdlet that I want to stop the Notepad process, it does not work because it recognizes that “notepad” is not a number, so we are not using the default parameter set. Also it is not using the Name parameter set because it does not accept the pipelined input. So, how can it work?

That is easy! Remove the word Notepad, and it works just fine. I know this will work because of the third parameter set, which accepts pipelined input:

Parameter Set Name: InputObject

Is default parameter set: False

 

  Parameter Name: InputObject

    ParameterType = System.Diagnostics.Process[]

    Position = 0

    IsMandatory = True

    IsDynamic = False

    HelpMessage =

    ValueFromPipeline = True

    ValueFromPipelineByPropertyName = False

    ValueFromRemainingArguments = False

    Aliases = {}

    Attributes =

      System.Management.Automation.ParameterAttribute

So, all I need to do is to pipe a process object to the Stop-Process cmdlet, and it will stop that process. I can see what process it stops by using the –PassThru parameter, as shown here:

PS C:\> get-Process notepad | Stop-Process -PassThru

 

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

     84       8     1488       8112    98     0.08   5412 notepad

LR, that is all there is to using the pipeline. Poshpourri Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Piping is very useful. Thanks for sharing