'Trapping a PowerShell Statement from Win32_Process into a Variable for Taskkill Command

This powershell statement looks for a long commandline string from a process java.exe - it uses the string server1 to trap this specific process. It returns the words Processid and Commandline with its relative values.

gwmi win32_process | select Processid,Commandline | where-object CommandLine -match "server1"

returns this line where 15112 is all I need:

Processid Commandline                                         
--------- -----------                                         
    15112 D:\ ..a long command string.

How would you trap the single PID number returned from the above PS statement in a variable to run a taskkill /pid $PIDNUM on ? Not sure how to extract that single number from the statement.



Solution 1:[1]

Very simple, we store the entire result into the variable $PIDNUM, and we can access the result object's properties using dot-notation

$PIDNUM = (gwmi win32_process | select Processid,Commandline | where-object CommandLine -match "server1").ProcessID
taskkill /pid $PIDNUM

or

$PIDNUM = gwmi win32_process | select Processid,Commandline | where-object CommandLine -match "server1"
taskkill /pid $PIDNUM.ProcessID

If your first statement finds multiple tasks, you'll need to run a loop to execute the taskkill for each object stored in the $PIDNUM variable

foreach ($num in $PIDNUM)
{
    taskkill /pid $num.processid
}

Solution 2:[2]

First, the obligatory pointer:

  • The CIM cmdlets (e.g., Get-CimInstance) superseded the WMI cmdlets (e.g., Get-WmiObject, whose built-in alias is gwmi) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) v6+, where all future effort will go, doesn't even have them anymore. Note that WMI still underlies the CIM cmdlets, however. For more information, see this answer.
$pidOfInterest = 
  (
    Get-CimInstance win32_process |
      Where-Object CommandLine -match server1
  ).ProcessId

Note:

  • $pidOfInterest may receive multiple PIDs (process IDs), given that multiple processes may match your Where-Object filter; that accessing .ProcessId directly on a potential array of values still works to extract its elements' property values is courtesy of PowerShell's member-access enumeration feature.

    • If $pidOfInterest does end up containing multiple PIDs, you can pass them to taskkill.exe as follows:

      taskkill $pidOfInterest.ForEach({ '/pid', $_ })
      
    • With Stop-Process (see below), it is simpler, because its -Id parameter accepts an array of PIDs:

      Stop-Process -Id $pidOfInterest
      
  • The select Processid,Commandline part of your command just creates unnecessary overhead, so it was omitted above - the Get-CimInstance output objects can be filtered directly.

  • You don't strictly need taskkill.exe for terminating processes, given that PowerShell has a Stop-Process cmdlet.

    • However, an important difference is that taskkill.exe attempts graceful, cooperative termination by default, whereas Stop-Process (as of PowerShell 7.2.3) invariably terminates forcefully - which is what taskkill.exe offers as an opt-int with /f

      • Improving Stop-Process in the future to support graceful, cooperative termination too is the subject of GitHub issue #13664.
    • Attempting graceful termination means that termination may not be effective, however.

    • See this answer for more information.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2