[C#] Lấy ID của tiến trình cha

Standard

http://www.rhyous.com/2010/04/30/how-to-get-the-parent-process-that-launched-a-c-application/

 

Đôi khi ta cần theo dõi một tiến trình nào đó, và chờ đợi đến khi nó kết thúc để bắt đầu thực hiện một thao tác khác (ví dụ như các trình uninstall-manager cần xóa ứng dụng khỏi danh sách sau khi đã được gỡ bỏ thành công). Trong một số trường hợp cụ thể, ta cần theo dõi cả một cây tiến trình (tức tiến trình x và mọi tiến trình con y được chạy bởi x) chứ không chỉ là một tiến trình, khi đó, phương thức WaitToExit() của lớp Process do .Net cung cấp là không đủ.

Ý tưởng đặt ra, là ta sẽ lưu ID của tiến trình x, và sau khi x.WaitToExit() hoàn tất ta sẽ kiểm tra các tiến trình đang chạy trong máy, nếu xuất hiện tiến trình y mà tiến trình cha của nó là x, thì ta lặp phương thức WaitToExit() đối với y, và tiếp tục như vậy…

Lớp Process của .Net không cho phép lấy thông tin về tiến trình cha, nhưng ta có thể thực hiện thông qua 3 API:

3 API này rất quen thuộc với những ai thường xuyên làm việc với tiến trình: API đầu tiên sẽ dùng để lấy thông tin về toàn bộ các tiến trình trong máy, API thứ hai để lấy thông tin về tiến trình đầu tiên, và API cuối để lấy các tiến trình tiếp theo. Thông tin về các tiến trình được lưu trong cấu trúc sau:


typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;
  DWORD     cntUsage;
  DWORD     th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;
  DWORD     th32ParentProcessID;
  LONG      pcPriClassBase;
  DWORD     dwFlags;
  TCHAR     szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;

chuyển qua C#:

private struct PROCESSENTRY32
{
    public uint dwSize;
    uint cntUsage;
    public uint th32ProcessID;
    IntPtr th32DefaultHeapID;
    uint th32ModuleID;
    uint cntThreads;
    public uint th32ParentProcessID;
    int pcPriClassBase;
    uint dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    string szExeFile;
}

(giá trị SizeConst được tham khảo từ đây).
Các khai báo cần thiết:

using System.Runtime.InteropServices;

 

[DllImport("kernel32.dll")]
private static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
[DllImport("kernel32.dll")]
private static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll")]
private static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

const int TH32CS_SNAPPROCESS = 2;

Hàm lấy ID của tiến trình cha, đầu vào là ID của tiến trình cần lấy thông tin:

public static int GetParentProcessID(int processID)
{
    IntPtr hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == IntPtr.Zero)
    {
        return -1;
    }

    PROCESSENTRY32 procEntry = new PROCESSENTRY32();
    procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

    if (!Process32First(hSnapshot, ref procEntry))
    {
        return -1;
    }

    int parentID = -1;
    while (parentID == -1)
    {
        if (procEntry.th32ProcessID == processID)
        {
            parentID = (int)procEntry.th32ParentProcessID;
            break;
        }
        if (!Process32Next(hSnapshot, ref procEntry))
        {
            break;
        }
    }

    return parentID;
}

Download

2 thoughts on “[C#] Lấy ID của tiến trình cha

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s