I was looking a lot for method to get parent process in .NET, but found only P/Invoke way.
A:
Here is managed way:
using System.Diagnostics;
var pc = new PerformanceCounter("Process",
"Creating Process ID",
Process.GetCurrentProcess().ProcessName);
return Process.GetProcessById((int)pc.NextValue());
abatishchev
2009-01-24 23:35:05
Your solution may not work if there are multiple processes with the same name. See: http://csharpfeeds.com/post/1743/Retrieving_the_Parent_Process_of_a_Child_when_Multiple_Instances_Exist_Robert_Villahermosa.aspx
Michael Hale
2010-02-25 17:51:38
As stated by Michael, this is a partial solution. With multiple instances off the same process, only 1 PID is returned.
Niels R.
2010-04-06 10:08:13
@Niels R.: agree with no doubt
abatishchev
2010-04-06 10:18:27
@romkyns: Edit to unvote? So nice
abatishchev
2010-10-29 07:24:06
@abat Yes, edit to unvote. Why not? I don't want any of my co-workers to use this solution because it only seems to work - until two instances with the same name are available. Perhaps I should have downvoted, like the two others did...
romkyns
2010-10-29 09:03:36
+7
A:
This code provides a nice interface for finding the Parent process object and takes into account the possibility of multiple processes with the same name:
Usage:
Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id);
Code:
public static class ProcessExtensions {
private static string FindIndexedProcessName(int pid) {
var processName = Process.GetProcessById(pid).ProcessName;
var processesByName = Process.GetProcessesByName(processName);
string processIndexdName = null;
for (var index = 0; index < processesByName.Length; index++) {
processIndexdName = index == 0 ? processName : processName + "#" + index;
var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
if (processId.NextValue().As<int>().Equals(pid)) {
return processIndexdName;
}
}
return processIndexdName;
}
private static Process FindPidFromIndexedProcessName(string indexedProcessName) {
var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
return Process.GetProcessById((int) parentId.NextValue());
}
public static Process Parent(this Process process) {
return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
}
}
Michael Hale
2010-02-25 17:53:29
It's coming from LiquidSyntax (http://code.google.com/p/liquidsyntax/). I thought I had removed all references to liquid syntax, but you caught one :)
Michael Hale
2010-06-16 18:16:51
+4
A:
Here is a solution. It uses p/invoke, but seems to work well, 32 or 64 cpu:
/// <summary>
/// A utility class to determine a process parent.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
// These members must match PROCESS_BASIC_INFORMATION
internal IntPtr Reserved1;
internal IntPtr PebBaseAddress;
internal IntPtr Reserved2_0;
internal IntPtr Reserved2_1;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
[DllImport("ntdll.dll")]
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
/// <summary>
/// Gets the parent process of the current process.
/// </summary>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess()
{
return GetParentProcess(Process.GetCurrentProcess().Handle);
}
/// <summary>
/// Gets the parent process of specified process.
/// </summary>
/// <param name="id">The process id.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(int id)
{
Process process = Process.GetProcessById(id);
return GetParentProcess(process.Handle);
}
/// <summary>
/// Gets the parent process of a specified process.
/// </summary>
/// <param name="handle">The process handle.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(IntPtr handle)
{
ParentProcessUtilities pbi = new ParentProcessUtilities();
int returnLength;
int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
if (status != 0)
throw new Win32Exception(status);
try
{
return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
catch (ArgumentException)
{
// not found
return null;
}
}
}
Simon Mourier
2010-07-27 17:09:02
It's actually managed, but not portable on another OS than Windows you're right. However, the notion of a parent process is not portable either, since it's not in the .NET Framework itself, so I don't think it's a big issue.
Simon Mourier
2010-07-28 07:57:26