CreateToolhelp32Snapshot (kernel32)
Last changed: -87.82.247.18

.
Summary

C# Signature:

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, uint th32ProcessID);

VB.NET Signature:

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function CreateToolhelp32Snapshot(ByVal dwFlags As SnapshotFlags, ByVal th32ProcessID As UInteger) As IntPtr
End Function

User-Defined Types:

SnapshotFlags

Notes:

You may find that you when calling CreateToolhelp32Snapshot that you must specify SnapshotFlag.NoHeaps in addition to any other flags or you will get an invalid handle and an "Out of Memory" error (ERROR_NOT_ENOUGH_MEMORY = 0x8). This is a seemingly undocumented flag. See the bottom of the MSDN page http://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx

Tips & Tricks:

Please add some!

Sample Code:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
static class myProcessEx
{  
    //inner enum used only internally
    [Flags]
    private enum SnapshotFlags : uint
    {
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F,
    NoHeaps = 0x40000000
    }
    //inner struct used only internally
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct PROCESSENTRY32
    {
    const int MAX_PATH = 260;
    internal UInt32 dwSize;
    internal UInt32 cntUsage;
    internal UInt32 th32ProcessID;
    internal IntPtr th32DefaultHeapID;
    internal UInt32 th32ModuleID;
    internal UInt32 cntThreads;
    internal UInt32 th32ParentProcessID;
    internal Int32 pcPriClassBase;
    internal UInt32 dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
    internal string szExeFile;
    }

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID);

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32First([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32Next([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle([In] IntPtr hObject);

    // get the parent process given a pid
    public static Process GetParentProcess(int pid)
    {
    Process parentProc = null;
    IntPtr handleToSnapshot = IntPtr.Zero;
    try
    {
        PROCESSENTRY32 procEntry = new PROCESSENTRY32();
        procEntry.dwSize = (UInt32)Marshal.SizeOf(typeof(PROCESSENTRY32));
        handleToSnapshot = CreateToolhelp32Snapshot((uint)SnapshotFlags.Process, 0);
        if (Process32First(handleToSnapshot, ref procEntry))
        {
        do
        {
            if (pid == procEntry.th32ProcessID)
            {
            parentProc = Process.GetProcessById((int)procEntry.th32ParentProcessID);
            break;
            }
        } while (Process32Next(handleToSnapshot, ref procEntry));
        }
        else
        {
        throw new ApplicationException(string.Format("Failed with win32 error code {0}", Marshal.GetLastWin32Error()));
        }
    }
    catch (Exception ex)
    {
        throw new ApplicationException("Can't get the process.", ex);
    }
    finally
    {
        // Must clean up the snapshot object!
        CloseHandle(handleToSnapshot);
    }
    return parentProc;
    }

    // get the specific parent process
    public static Process CurrentParentProcess
    {
    get
    {
        return GetParentProcess(Process.GetCurrentProcess().Id);
    }
    }

    static void Main()
    {
    Process pr = CurrentParentProcess;

    Console.WriteLine("Parent Proc. ID: {0}, Parent Proc. name: {1}", pr.Id, pr.ProcessName);
    }
}

See also:

PROCESSENTRY32, Process32First, Process32Next

Alternative Managed API:

Do you know one? Please contribute it!

Documentation