public static int GetParentProcessId(int processId)
        {
            // This may be inconsistent with snapshot but when the call returns it it not guaranteed to be consistent anyway.
            EnsureProcessExists(processId);

            IntPtr snapshot = IntPtr.Zero;

            try
            {
                snapshot = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPPROCESS, 0);
                if (snapshot.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE)
                {
                    throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                NativeMethods.PROCESSENTRY32 pe = new NativeMethods.PROCESSENTRY32();
                pe.dwSize = (uint)Marshal.SizeOf(pe);

                bool found = NativeMethods.Process32First(snapshot, ref pe);
                while (found)
                {
                    if (pe.th32ProcessID == processId)
                    {
                        return((int)pe.th32ParentProcessID);
                    }
                    found = NativeMethods.Process32Next(snapshot, ref pe);
                }

                // Report ArgumentException(processId) in the consistent way.
                NativeMethods.SetLastError(NativeMethods.ERROR_INVALID_PARAMETER);
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            finally
            {
                if (snapshot != IntPtr.Zero)
                {
                    NativeMethods.CloseHandle(snapshot);
                }
            }
        }
        public static int GetParentProcessId(int processId)
        {
            // This may be inconsistent with snapshot but when the call returns it it not guaranteed to be consistent anyway.
            EnsureProcessExists(processId);

            IntPtr snapshot = IntPtr.Zero;
            try
            {
                snapshot = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPPROCESS, 0);
                if (snapshot.ToInt64() == NativeMethods.INVALID_HANDLE_VALUE)
                {
                    throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                NativeMethods.PROCESSENTRY32 pe = new NativeMethods.PROCESSENTRY32();
                pe.dwSize = (uint)Marshal.SizeOf(pe);

                bool found = NativeMethods.Process32First(snapshot, ref pe);
                while (found)
                {
                    if (pe.th32ProcessID == processId)
                    {
                        return (int)pe.th32ParentProcessID;
                    }
                    found = NativeMethods.Process32Next(snapshot, ref pe);
                }

                // Report ArgumentException(processId) in the consistent way.
                NativeMethods.SetLastError(NativeMethods.ERROR_INVALID_PARAMETER);
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            finally
            {
                if (snapshot != IntPtr.Zero)
                {
                    NativeMethods.CloseHandle(snapshot);
                }
            }
        }