What's the difference Select ID vs Stop-Process ID

I am trying to figure out the why in the following codes. A “why” explanation would be appreciated.

When I run the following code, select-object displays the piped object ID.

get-process | where {$_.name -eq 'ytd'} | select ID

The stop-process ID works if the object ID from the above code is hardwired.

Stop-Process ####

If I run the following code, PowerShell returns an error

get-process | where {$_.name -eq 'ytd'} | Stop-Process ID

Of course, this following would work and I understood why (Stop-Process is piped the object).

get-process | where {$_.name -eq 'ytd'} | Stop-Process

The question is what’s the difference between the Stop-Process ID vs Select-Object ID; the object is piped to both cmdlets.

What’s the error message? Stop-process is probably trying to get the ID from both the pipe and what follows it at the same time.

Recap the above post:

get-process | where {$_.name -eq 'ytd'} | select ID # Select output the process ID number
Stop-Process ID # Use the ID number returned from above, it worked 
get-process | where {$_.name -eq 'ytd'} | Stop-Process # No ID, it killed the process - ID was not needed
get-process | where {$_.name -eq 'ytd'} | Stop-Process ID # error (see below); 
# Trying to understand the difference between line 2 Stop-Process ID and the piped Stop-Process ID

I understood that ID after Stop-Process was not needed; however I was trying to understand why and how:

get-process | where {$_.name -eq 'ytd'} | Stop-Process ID

The following error was returned:

Stop-Process : Cannot bind parameter 'InputObject'. Cannot convert the "ID" value of type
"System.String" to type "System.Diagnostics.Process".
At line:1 char:56
+ get-process | where {$_.name -eq 'ytd'} | Stop-Process ID
+                                                        ~~
    + CategoryInfo          : InvalidArgument: (:) [Stop-Process], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.StopProcess

ID string was returned to Select-Object above and Stop-Process ID (integer) was parsed to successfully as well.

Why when it was piped, Stop-Process looked for System.Diagnostic.Process data type as in the error message.


when you use the Stop-Process cmdlet alone, then it requires an input to understand which process to stop(either ID or ProcessName), but when using the same cmdlet in a pipeline(chaining of cmdlets), then the required input is taken from pipeline and should not be passed (Get-Process -Name something | Stop-Process -Id $ID). It will understand what to consume from the pipeline object and proceed. Most of the builtin cmdlets in PowerShell has this capability.

see more here: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipelines?view=powershell-5.1

Thanks for the link.

The explanation made it clear. It makes sense if the cmdlet understood the piped object, else (in this case) the ID must be extracted from the object and parse to the next cmdlet.

Select-Object will infer that you mean to pass the first provided value to -Property and select the requested properties for you; its -Property parameter is defined as accepting positional input (i.e., not using the explicit parameter name) and as such accepts it when you use Select-Object ID – this is entirely equivalent to Select-Object -Property ID, you’re passing it a string value (or array of string values, depending on how you want to work with it) indicating the property or properties you want it to keep.

Stop-Process’s first parameter, however, is -Id – yes, it has the same name as the property you’re selecting above, but when you use Stop-Process Id you’re not specifying a parameter name, you’re passing a value… and Stop-Process doesn’t take a string value for its first positional parameter (-Id takes a number, not a string).

You can see parameter details for any function (including if they can be passed by position, which position they are when multiple parameter values are supplied, whether they can take pipeline input) by using Get-Help <command-name> -Parameter <parameter-name> – to see all the parameters for Stop-Process you can use Get-Help Stop-Process -Parameter *