1

I need help with killing child process but keep parent safe. I'm new to powershell scripting [obviously]. Here's exactly what I need:

I have processes that are using more than 500 000K of memory and I want to put them down by script that will run daily. But in the same time I want to avoid killing parent process which can also fall in the "above 500 000" category. I want to use it for something else but as an example I'm showing iexplore.exe tree. iexplore

Two of child processes are breaching my memory max. I'm able to kill those by script, but I need to put fail safe option in case parent process will also go above specified limit and that I'm not sure how to aproach.

This is what I have so far. First step is to get all breaching processes:

Get-WmiObject -ComputerName $[list of servers] Win32_Process -Filter "name = '[app name]'" | Select-Object __Server,Name,@{Name='WorkingSet';Expression={[math]::Round(($_.WS/1MB),2)}},@{Name='VirtualMemory';Expression={[math]::Round(($_.VM/1MB),2)}} | Where-Object {$_.WorkingSet -gt $[my threshold]}

Next step would be to stop them.

I would be grateful for any hints.

Jules

2 Answers 2

1

Using WMI, you can get the ParentProcessID of process

gwmi -Class win32_process -Filter 'name like "%iexplore%"' | 
    select Name, ProcessID, ParentProcessID

On a side note: while unlikely in the iexplore case, it's entirely possible for a parent process to stop and the id being reused by another process.

1
  • Thanks, that would be useful if it would list only one parentprocessid but in most cases there are at least two and even four in my case. I think that I need something that would exclude processes that have a child process from stopping.
    – jules d
    Commented Dec 12, 2017 at 10:45
0

This is one way you can create that kind of list. First, store all of the PIDs for the process name in question in an array. Then filter the process list to only include those where the Parent PID is also in that array. This works because the parent of the iexplore children will be another iexplore that is in the PID array, and the parent of the FIRST iexplore proces was probably Explorer, whose PID is not in that array.

$pids = (gwmi -Class win32_process -Filter 'name like "%iexplore%"' | select processid).processid
"PIDs"
$pids
"All Children"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids } | select -prop commandline,processid
"Children > Size"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | select -prop commandline,processid
"Parent(s)"
gwmi -Class win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -notin $pids } | select -prop commandline,processid

Note that you cannot do this with a single pipeline that begins with Get-WmiObject -ComputerName $[list of servers]. That creates a single collection of processes across multiple devices. There is no parent process relationship between processes on different devices. You will need to nest the process enumeration inside of a loop that runs against each server.

foreach ($server in $listOfServers) {
    $pids = (gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | select processid).processid
    # Report only, no kill
    gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | select -prop commandline,processid
    # Kill, uncomment to enable
    # gwmi -comp $server win32_process -Filter 'name like "%iexplore%"' | where { $_.parentprocessid -in $pids -and $_.ws -gt 500MB } | foreach { $_.terminate() }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .