CreateToolhelp32Snapshot may help you find parent (==associated?) process ID.
For example let's assume you'd like to kill all "ScreenScraper.exe" processes with no parent process (i.e. those hanged during normal closedown process). The code then may look like this:
class Program
{
static void Main(string[] args)
{
string procName = "ScreenScraper"; // Mind no ".exe" extension here
foreach (var process in Process.GetProcessesByName(procName))
{
try
{
var parent = myProcessEx.GetParentProcess(process.Id);
Console.WriteLine("{0} {1}; PARENT: {2} {3}",
process.Id, process.ProcessName, parent.Id, parent.ProcessName);
}
catch (ApplicationException exception)
{
if (exception.InnerException is ArgumentException)
{
Console.WriteLine("An orphan '{0}' process found with PID {1}. Killing it...",
process.Id, process.ProcessName);
process.Kill();
}
else
throw;
}
}
}
}
The myProcessEx
class is taken from the sample code section of http://www.pinvoke.net/default.aspx/kernel32.createtoolhelp32snapshot.
Note that a terminated parent process ID may be reused (https://stackoverflow.com/a/185298/4295017) so you probably need to elaborate the parent check code a little bit more.