/// <summary>
        ///
        /// </summary>
        /// <param name="accessRights">Desired access rights for process handle</param>
        /// <param name="pid">Process ID</param>
        /// <returns>Handle to process or <see cref="IntPtr.Zero"/> if process doesn't exists</returns>
        /// <exception cref="Win32Exception">Unexpected WinApi error</exception>
        public static IntPtr OpenProcessHandle(ProcessAccessRights accessRights, int pid)
        {
            var handle = IntPtr.Zero;

            try
            {
                handle = Kernel32.OpenProcess(accessRights, false, pid);
                if (handle == IntPtr.Zero)
                {
                    var errorCode = Marshal.GetLastWin32Error();
                    if (errorCode == (int)ErrorCodes.ERROR_INVALID_PARAMETER)
                    {
                        return(IntPtr.Zero); // ERROR_INVALID_PARAMETER means that process doesn't exist. Don't throw exception here, because this error is expected and shouldn't crash ctor's
                    }
                    Win32ExceptionUtility.Throw(errorCode);
                }
            }
            catch
            {
                Kernel32.CloseHandle(handle);
                throw;
            }

            return(handle);
        }
        public static void EnsureProcessIsRunning(IntPtr handle, int pid)
        {
            if (handle == IntPtr.Zero)
            {
                ThrowOnNonExistentProcess(pid);
            }

            if (!Kernel32.GetExitCodeProcess(handle, out var exitCode))
            {
                Win32ExceptionUtility.Throw();
            }

            if (exitCode != ProcessExitCodes.STILL_ALIVE)
            {
                ThrowOnProcessExit(pid);
            }
        }