masiboo
masiboo

Reputation: 4719

Trying to find and kill a process by PowerShell script

I have the following script to find the process "dotnet.exe". In my system, I have many dotnet.exe processes running. But I want to kill the "dotnet.exe" which has command line argument "MyService\Web\argument". I'm trying to do it by the following script. But it doesn't find anything, although I see the process in the Task Manager.

$process = Get-WmiObject Win32_Process | select name, commandline

foreach ($p in $process)
{
    if ($p.name -contains "dotnet.exe" -and $p.commandline -contains "web")
    {
        $kp =    Get-Process $p;
        $kp.CloseMainWindow();
        if (!$kp.HasExited)
        {
            $kp | Stop-Process -Force
        }
    }
    else
    {
        Write-Host name: $p.name and param: $p.commandline;
    }
}

Upvotes: 3

Views: 8120

Answers (2)

MisterSeajay
MisterSeajay

Reputation: 4659

The Get-WmiObject cmdlet returns quite useful objects, but you have stripped off everything by selecting only the Name and CommandLine parameters:

$process = Get-WmiObject Win32_Process | select name, commandline

If you remove the | select name, commandline part, you can still loop through each process but also make use of methods like Terminate() that will still be available.

You could do it in one shot, as per @ansgar-wiechers comment, or still make use of the loop and add in more logging, etc. if you wanted:

$process = Get-WmiObject Win32_Process

foreach($p in $process){
    if($p.Name -eq "*dotnet.exe" -and $p.CommandLine -like "*web*"){
       $p.Terminate()
       # and so on... 
    }
}

Note also the comment from @TheIncorrigible1 about the use of comparison operators. I have used -eq for the process name and -like for the command line.

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200193

All you need to do is filter the process list directly via Get-WmiObject and then terminate the matching process(es):

$fltr = "name like '%dotnet.exe%' and commandline like '%web%'"
Get-WmiObject Win32_Process -Filter $fltr | ForEach-Object {
    $_.Terminate()
}

You could also call Terminate() directly on the output of Get-WmiObject like this:

(Get-WmiObject Win32_Process -Filter $fltr).Terminate()

However, there are situations where this could fail, e.g. if Get-WmiObject doesn't return any results, or if you're using PowerShell v2 or earlier and Get-WmiObject returns more than one result (passing a method call to the members of an array requires member enumeration, which was introduced with PowerShell v3). Using a ForEach-Object loop is both more robust and backwards-compatible.

Upvotes: 3

Related Questions