найти дерево процессов в .NET - PullRequest
3 голосов
/ 13 февраля 2009

Я ищу простой способ найти дерево процессов (как показывают такие инструменты, как Process Explorer) на C # или другом языке .NET. Также было бы полезно найти аргументы командной строки другого процесса (StartInfo для System.Diagnostics.Process кажется недопустимым для процесса, отличного от текущего процесса).

Я думаю, что это можно сделать, только вызвав API win32, но я был бы счастлив, если бы ошибался.

Ответы [ 4 ]

5 голосов
/ 26 марта 2010

Если вы не хотите P / Invoke, вы можете получить родительские идентификаторы со счетчиком производительности:

foreach (var p in Process.GetProcesses())
{
   var performanceCounter = new PerformanceCounter("Process", "Creating Process ID", p.ProcessName);
   var parent = GetProcessIdIfStillRunning((int)performanceCounter.RawValue);
   Console.WriteLine(" Process {0}(pid {1} was started by Process {2}(Pid {3})",
              p.ProcessName, p.Id, parent.ProcessName, parent.ProcessId );
}

//Below is helper stuff to deal with exceptions from 
//looking-up no-longer existing parent processes:

struct MyProcInfo
{
    public int ProcessId;
    public string ProcessName;
}

static MyProcInfo GetProcessIdIfStillRunning(int pid)
{
    try
    {
        var p = Process.GetProcessById(pid);
        return new MyProcInfo() { ProcessId = p.Id, ProcessName = p.ProcessName };
    }
    catch (ArgumentException)
    {
        return new MyProcInfo() { ProcessId = -1, ProcessName = "No-longer existant process" };
    }
}

Теперь просто поместите его в любую древовидную структуру, и все готово.

2 голосов
/ 13 февраля 2009

Вы также можете попробовать заглянуть в WMI (например, класс Win32_Process).

Вот пример получения командной строки процесса по его идентификатору процесса:

                using (var mos = new ManagementObjectSearcher(
                    "SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + pid))
                {
                    foreach (var obj in mos.Get())
                    {
                        object data = obj.Properties["CommandLine"].Value;
                        if (data != null)
                        {
                            Console.WriteLine("{0}: commandline = {1}", pid, data.ToString());
                        }
                    }
                }
            }
        }

Я скопировал это из кода, который я недавно написал. Для ваших целей вы можете использовать другие методы (например, получение нескольких свойств и / или процессов одновременно). Но вы поняли.

РЕДАКТИРОВАТЬ: ID родительского процесса, который вам понадобится для построения дерева, это, например, свойство "ParentProcessId".

Полагаю, однако, использование Win32 API быстрее. Обратите внимание, что не все функции, которые вам необходимы, также справедливо доступны. Для некоторых вещей вы должны прибегнуть к (несколько) неподдерживаемой функции NtQueryProcessInformation () или другим из NTDLL.

2 голосов
/ 22 февраля 2009

Я не понимаю, почему вы не хотите p / invoke. Если вы посмотрите на System.Diagnostics в Reflector, вы увидите, что он использует p / вызывает внутренне. В любом случае, класс Process не имеет способ получения родительского PID процесса. Вместо этого:

Определение структуры:

[StructLayout(LayoutKind.Sequential)]
struct PROCESS_BASIC_INFORMATION
{
    public int ExitStatus;
    public int PebBaseAddress;
    public int AffinityMask;
    public int BasePriority;
    public int UniqueProcessId;
    public int InheritedFromUniqueProcessId;
}

(упрощенная) функция импорта:

[DllImport("ntdll.dll")]
static extern int NtQueryInformationProcess(
    IntPtr ProcessHandle,
    int ProcessInformationClass,
    out PROCESS_BASIC_INFORMATION ProcessInformation,
    int ProcessInformationLength,
    out int ReturnLength
    );

код:

Process p = Process.GetProcessById(1234);
PROCESS_BASIC_INFORMATION pbi;
int size;

NtQueryInformationProcess(p.Handle, 0, out pbi, Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)), out size);
// pbi.InheritedFromUniqueProcessId now contains the process' parent PID

Вам нужно будет вставить эти символы вверху файла:

using System.Runtime.InteropServices;
using System.Diagnostics;

Если вы хотите перечислить процессы, вам лучше использовать NtQuerySystemInformation - хотя этот код слишком длинный для размещения здесь.

0 голосов
/ 13 февраля 2009

Я почти уверен, что для этого вам понадобится WinAPI. См. этот фрагмент кода в качестве примера. Это будет довольно стандартный алгоритм построения дерева из списка объектов и их родительских объектов.

...