Piping Results from One PowerShell Cmdlet to Another

Doctor Scripto

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 

0 comments

Discussion is closed.

Feedback usabilla icon