Пример #1
0
 public bool WaitForExit(int millisecondsTimeout)
 {
     if (hasExited)
     {
         return(true);
     }
     if (!wasStarted)
     {
         throw new InvalidOperationException("Process was not yet started");
     }
     if (safeProcessHandle.IsClosed)
     {
         throw new ObjectDisposedException("ProcessRunner");
     }
     using (var waitHandle = new ProcessWaitHandle(safeProcessHandle))
     {
         if (waitHandle.WaitOne(millisecondsTimeout, false))
         {
             if (!GetExitCodeProcess(safeProcessHandle, out exitCode))
             {
                 throw new Win32Exception();
             }
             // Wait until the output is processed
             //					if (standardOutputTask != null)
             //						standardOutputTask.Wait();
             //					if (standardErrorTask != null)
             //						standardErrorTask.Wait();
             hasExited = true;
         }
     }
     return(hasExited);
 }
Пример #2
0
 /// <summary>
 /// Asynchronously waits for the process to exit.
 /// </summary>
 public Task WaitForExitAsync()
 {
     if (hasExited)
     {
         return(Task.FromResult(true));
     }
     if (!wasStarted)
     {
         throw new InvalidOperationException("Process was not yet started");
     }
     if (safeProcessHandle.IsClosed)
     {
         throw new ObjectDisposedException("ProcessRunner");
     }
     lock (lockObj)
     {
         if (waitForExitTCS == null)
         {
             waitForExitTCS                       = new TaskCompletionSource <object>();
             waitForExitAsyncWaitHandle           = new ProcessWaitHandle(safeProcessHandle);
             waitForExitAsyncRegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(waitForExitAsyncWaitHandle, WaitForExitAsyncCallback, null, -1, true);
         }
         return(waitForExitTCS.Task);
     }
 }
Пример #3
0
        IntPtr GetProcessHandle(Kernel32.ProcessAccessFlags access, bool throwIfExited)
        {
            if (_haveProcessHandle)
            {
                if (throwIfExited)
                {
                    // Since haveProcessHandle is true, we know we have the process handle
                    // open with at least SYNCHRONIZE access, so we can wait on it with
                    // zero timeout to see if the process has exited.
                    ProcessWaitHandle waitHandle = null;
                    try {
                        waitHandle = new ProcessWaitHandle(_processHandle);
                        if (waitHandle.WaitOne(0, false))
                        {
                            throw new InvalidOperationException("Process has exited");
                        }
                    } finally {
                        waitHandle?.Close();
                    }
                }
                return(_processHandle);
            }

            var handle = Kernel32.OpenProcess(access, false, _inner.Id);

            if (throwIfExited && (access & Kernel32.ProcessAccessFlags.QueryInformation) != 0)
            {
                if (Kernel32.GetExitCodeProcess(handle, out var exitCode) && exitCode != Kernel32.STILL_ACTIVE)
                {
                    throw new InvalidOperationException("Process has exited");
                }
            }

            return(handle);
        }
Пример #4
0
        /// <summary>
        /// Asynchronously waits for the process to exit.
        /// </summary>
        public static Task WaitForExitAsync(this Process process)
        {
            if (process.HasExited)
            {
                return(Task.CompletedTask);
            }
            var safeProcessHandle = process.SafeHandle;

            if (safeProcessHandle.IsClosed)
            {
                throw new ObjectDisposedException("Process");
            }
            var tcs        = new TaskCompletionSource <object?>();
            var waitHandle = new ProcessWaitHandle(safeProcessHandle);
            RegisteredWaitHandle?registeredWaitHandle = null;

            lock (tcs) {
                registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(waitHandle, WaitForExitAsyncCallback, null, -1, true);
            }
            return(tcs.Task);

            void WaitForExitAsyncCallback(object context, bool wasSignaled)
            {
                // The lock is used to ensure `registeredWaitHandle` is initialized here
                // even if the process terminates while `RegisterWaitForSingleObject` is returning.
                lock (tcs) {
                    registeredWaitHandle !.Unregister(null);
                }
                waitHandle.Close();
                tcs.SetResult(null);
            }
        }
Пример #5
0
 public bool WaitForExit(int exitTime = -1)
 {
     using (var wait = new ProcessWaitHandle(proc))
     {
         return(wait.WaitOne(exitTime));
     }
 }
Пример #6
0
 public bool WaitForExit(TimeSpan timeout)
 {
     if (IsInvalid || IsClosed)
     {
         return(true);
     }
     using (var waitHandle = new ProcessWaitHandle(this))
     {
         return(waitHandle.WaitOne(timeout));
     }
 }
Пример #7
0
 private void WaitForExitAsyncCallback(object context, bool wasSignaled)
 {
     waitForExitAsyncRegisteredWaitHandle.Unregister(null);
     waitForExitAsyncRegisteredWaitHandle = null;
     waitForExitAsyncWaitHandle.Close();
     waitForExitAsyncWaitHandle = null;
     // Wait until the output is processed
     //			if (standardOutputTask != null)
     //				await standardOutputTask;
     //			if (standardErrorTask != null)
     //				await standardErrorTask;
     waitForExitTCS.SetResult(null);
 }
Пример #8
0
        private void MonitorBrokerProcess()
        {
            var monitoringHandles = new WaitHandle[2];

            monitoringHandles[0] = _stopSignal;
            int relaunchCount       = 0;
            int pauseBeforeRelaunch = 0;

            while (true)
            {
                try
                {
                    _logger.Info("Waiting for stop signal or broker process termination");
                    // launch/re-launch/get JSI process
                    monitoringHandles[1] = new ProcessWaitHandle(GetMessageBrokerProcess().Handle);

                    // Wait for stop signal or broker process termination
                    var signaledIndex = WaitHandle.WaitAny(monitoringHandles);

                    // If, stop signal recieved, stop monitoring
                    if (signaledIndex == 0)
                    {
                        _logger.Info("Received stop signal. Stopping the monitoring of broker process.");

                        // Release the monitoring mutex
                        _monitoringOwnershipMutex.ReleaseMutex();
                        return;
                    }

                    // After every 20 relaunches we reset
                    if (relaunchCount > 20)
                    {
                        relaunchCount = 0;
                    }

                    relaunchCount++;
                    // For each relaunch increase the pause time between relaunches by 2 seconds
                    pauseBeforeRelaunch = relaunchCount * 2;

                    _logger.Info(string.Format("The broker process will restart in {0} seconds", pauseBeforeRelaunch));
                    Thread.Sleep(pauseBeforeRelaunch * 1000);
                }
                catch (Exception ex)
                {
                    _logger.Error("Error monitoring broker process. Trying again", ex);
                }
            }
        }
Пример #9
0
        static void Main(string[] args)
        {
            const int numProcesses = 5;

            var processes = new ProcessWaitHandle[numProcesses];

            for (int i = 0; i < numProcesses; i++)
            {
                var process = Process.Start(i % 2 == 0 ? "notepad" : "mspaint");
                Console.WriteLine($"Started {process.ProcessName} (PID={process.Id}...");
                processes[i] = new ProcessWaitHandle(process);
            }
            Console.WriteLine("Waiting for these processes to exit...");

            WaitHandle.WaitAll(processes);
            Console.WriteLine("All processes exited!");
        }
    static void Main(string[] args)
    {
        int processesCount = 42;
        var processes      = new Process[processesCount];
        var waitHandles    = new WaitHandle[processesCount];

        try
        {
            for (int i = 0; processesCount > i; ++i)
            {
                // exit immediately with return code i
                Process process = Process.Start(
                    "cmd.exe",
                    Invariant($"/C \"exit {i}\""));
                processes[i]   = process;
                waitHandles[i] = new ProcessWaitHandle(process);
            }
            WaitHandle.WaitAll(waitHandles);
            foreach (Process p in processes)
            {
                Console.Error.WriteLine(
                    Invariant($"process with Id {p.Id} exited with code {p.ExitCode}"));
            }
        }
        finally
        {
            foreach (Process p in processes)
            {
                p?.Dispose();
            }
            foreach (WaitHandle h in waitHandles)
            {
                h?.Dispose();
            }
        }
        Console.WriteLine("Press any key to continue...");
        Console.ReadKey(false);
    }
Пример #11
0
        public bool WaitForExitSafe(int milliseconds)
        {
            var  handle = IntPtr.Zero;
            bool exited;
            ProcessWaitHandle processWaitHandle = null;

            try {
                handle = GetProcessHandle(Kernel32.ProcessAccessFlags.Synchronize, false);
                if (handle == IntPtr.Zero || handle == new IntPtr(-1))
                {
                    exited = true;
                }
                else
                {
                    processWaitHandle = new ProcessWaitHandle(handle);
                    if (processWaitHandle.WaitOne(milliseconds, false))
                    {
                        exited    = true;
                        _signaled = true;
                    }
                    else
                    {
                        exited    = false;
                        _signaled = false;
                    }
                }
            } finally {
                processWaitHandle?.Close();
                ReleaseProcessHandle(handle);
            }

            if (exited && _watchForExit)
            {
                RaiseOnExited();
            }

            return(exited);
        }
Пример #12
0
        }         // proc CreateProcessPipe

        public bool StartProcess()
        {
            var errorLogged = false;

            try
            {
                if (IsProcessRunning)
                {
                    StopProcess();
                }

                SafeFileHandle hInput       = null;
                SafeFileHandle hOutput      = null;
                SafeFileHandle hError       = null;
                var            hEnvironment = default(GCHandle);
                using (var msg = Log.GetScope(LogMsgType.Information, stopTime: true))
                    using (var startupInfo = new NativeMethods.STARTUPINFO())
                    {
                        msg.WriteLine("Start process...");

                        try
                        {
                            // Create command line
                            var command = new StringBuilder();

                            var fileName = ConfigNode.GetAttribute <string>("filename");
                            if (!String.IsNullOrEmpty(fileName))
                            {
                                if (fileName.Length > 0 && fileName[0] == '"' && fileName[fileName.Length] == '"')
                                {
                                    command.Append(fileName);
                                }
                                else
                                {
                                    command.Append('"').Append(fileName).Append('"');
                                }
                            }

                            var argumentsAttr = Config.GetAttribute("arguments", String.Empty);
                            if (!String.IsNullOrEmpty(argumentsAttr))
                            {
                                command.Append(' ').Append(argumentsAttr);
                            }
                            var argumentsElement = Config.Element(xnArguments);
                            if (argumentsElement != null && !String.IsNullOrEmpty(argumentsElement.Value))
                            {
                                command.Append(' ').Append(argumentsElement.Value);
                            }

                            if (command.Length == 0)
                            {
                                throw new ArgumentException("@filename", "Filename is missing.");
                            }

                            // Working-Directory
                            var workingDirectory = Config.GetAttribute("workingDirectory", null);

                            // Run program as a different user
                            var domain   = ConfigNode.GetAttribute <string>("domain");
                            var userName = ConfigNode.GetAttribute <string>("username");
                            var password = ConfigNode.GetAttribute <SecureString>("password");
                            if (!String.IsNullOrEmpty(userName))
                            {
                                msg.WriteLine("Logon user...");
                                using (var pPassword = password.GetPasswordHandle())
                                {
                                    if (!NativeMethods.LogonUser(userName, domain, pPassword.DangerousGetHandle(),
                                                                 Environment.UserInteractive
                                                                                ? NativeMethods.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE
                                                                                : NativeMethods.LOGON_TYPE.LOGON32_LOGON_SERVICE,
                                                                 NativeMethods.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hUser))
                                    {
                                        throw new Win32Exception();
                                    }
                                }
                            }

                            // Create environment for the user
                            msg.WriteLine("Create environment...");
                            hEnvironment = GCHandle.Alloc(CreateEnvironment(hUser, userName, ConfigNode.GetAttribute <bool>("loadUserProfile")), GCHandleType.Pinned);

                            // Flags for the process
                            var flags = NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NEW_PROCESS_GROUP | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_SUSPENDED;

                            // Create start parameter
                            msg.WriteLine("Create pipes...");
                            startupInfo.dwFlags = 0x00000100;
                            CreateProcessPipe(true, out hInput, out startupInfo.hStdInput);
                            CreateProcessPipe(false, out hOutput, out startupInfo.hStdOutput);
                            CreateProcessPipe(false, out hError, out startupInfo.hStdError);

                            startupInfo.lpDesktop = String.Empty;

                            var processinformation = new NativeMethods.PROCESS_INFORMATION();
                            try
                            {
                                if (hUser == IntPtr.Zero)
                                {
                                    msg.WriteLine("Create process...");
                                    if (!NativeMethods.CreateProcess(null, command, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation))
                                    {
                                        throw new Win32Exception();
                                    }
                                }
                                else
                                {
                                    // user32.dll failed to initialize under system context?
                                    msg.WriteLine("Create process as user...");
                                    if (!NativeMethods.CreateProcessAsUser(hUser, null, command, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation))
                                    {
                                        throw new Win32Exception();
                                    }
                                    //if (!NativeMethods.CreateProcessWithTokenW(hUser, 1, null, command, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation))
                                    //	throw new Win32Exception();
                                }

                                // Create the .net process-objekt
                                process = Process.GetProcessById(processinformation.dwProcessId);
                                msg.WriteLine("Process crreated (ProcessId: {0}; Session: {1})", process.Id, process.SessionId);

                                // Create pipes
                                var inputEncoding  = Config.Attribute("inputEncoding") == null ? null : ConfigNode.GetAttribute <Encoding>("inputEncoding");
                                var outputEncoding = Config.Attribute("outputEncoding") == null ? null : ConfigNode.GetAttribute <Encoding>("outputEncoding");
                                inputStream = new StreamWriter(new FileStream(hInput, FileAccess.Write, 4096, false), inputEncoding ?? Console.InputEncoding)
                                {
                                    AutoFlush = true
                                };
                                outputStream = new StreamReader(new FileStream(hOutput, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding);
                                errorStream  = new StreamReader(new FileStream(hError, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding);

                                exitWaitHandle   = new ProcessWaitHandle(processinformation.hProcess);
                                waitForExitEvent = new ManualResetEventSlim(false);
                                waitHandle       = ThreadPool.RegisterWaitForSingleObject(exitWaitHandle, ProcessExited, process, -1, true);

                                arOutputStream = procProcessLogLine.BeginInvoke(LogMsgType.Information, outputStream, null, outputStream);
                                arErrorStream  = procProcessLogLine.BeginInvoke(LogMsgType.Warning, errorStream, null, errorStream);

                                // Run application
                                msg.WriteLine("Resume process...");
                                NativeMethods.ResumeThread(processinformation.hThread);
                            }
                            finally
                            {
                                NativeMethods.CloseHandle(processinformation.hThread);
                            }

                            msg.WriteLine("Successful loaded.");
                        }
                        catch (Exception e)
                        {
                            if (hUser != IntPtr.Zero)
                            {
                                NativeMethods.CloseHandle(hUser);
                            }
                            if (hInput != null && !hInput.IsInvalid)
                            {
                                hInput.Close();
                            }
                            if (hOutput != null && !hOutput.IsInvalid)
                            {
                                hOutput.Close();
                            }
                            if (hError != null && !hError.IsInvalid)
                            {
                                hError.Close();
                            }

                            msg.WriteException(e);
                            errorLogged = true;
                            throw;
                        }
                        finally
                        {
                            if (hEnvironment.IsAllocated)
                            {
                                hEnvironment.Free();
                            }
                        }
                    }

                CallMemberDirect("ProcessStarted", new object[] { process }, throwExceptions: false);
                HttpRefreshProperties();

                return(true);
            }
            catch (Exception e)
            {
                if (!errorLogged)
                {
                    Log.LogMsg(LogMsgType.Error, e.GetMessageString());
                }
                return(false);
            }
        }         // proc StartProcess
Пример #13
0
        public int Run()
        {
            STARTUPINFO si = new STARTUPINFO();
            si.lpDesktop = this.Desktop;
            PROCESSINFO pi = new PROCESSINFO();

            int creationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT;
            creationFlags |= this.CreateNoWindow ? CREATE_NO_WINDOW : 0;

            // This creates the default environment block for this user. If you need
            // something custom skip te CreateEnvironmentBlock (and DestroyEnvironmentBlock)
            // calls. You need to handle the allocation of the memory and writing to
            // it yourself.
            IntPtr envBlock;
            if (!CreateEnvironmentBlock(out envBlock, this.mSessionTokenHandle, 0))
            {
                throw new System.ComponentModel.Win32Exception();
            }

            try
            {
                CreateProcessAsUser(this.mSessionTokenHandle, this.mApplicationPath, this.CommandLine, IntPtr.Zero, IntPtr.Zero, 0, creationFlags, envBlock, this.WorkingDirectory, si, pi);
                ProcessWaitHandle waitable = new ProcessWaitHandle(pi.hProcess);
                if (waitable.WaitOne())
                {
                    return pi.dwProcessId;
                }
            }
            catch (Win32Exception)
            {
            }
            finally
            {
                DestroyEnvironmentBlock(envBlock);
            }

            return -1;
        }
Пример #14
0
 public ProcessExitMonitor(ProcessHandle processHandle)
 {
     _processWaitHandle = new ProcessWaitHandle(processHandle);
     ThreadPool.RegisterWaitForSingleObject(_processWaitHandle, HandleExited, null, -1, true);
 }
Пример #15
0
 public bool WaitForExit(TimeSpan timeout)
 {
     if (IsInvalid || IsClosed)
     {
         return true;
     }
     using (var waitHandle = new ProcessWaitHandle(this))
     {
         return waitHandle.WaitOne(timeout);
     }
 }
Пример #16
0
        private static unsafe int ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine)
        {
            IntSecurity.UnmanagedCode.Demand();

            FileStream output;
            FileStream error;

            int retValue = 0;

            if (outputName == null || outputName.Length == 0)
            {
                outputName = tempFiles.AddExtension("out");
            }

            if (errorName == null || errorName.Length == 0)
            {
                errorName = tempFiles.AddExtension("err");
            }

            // Create the files
            output = CreateInheritedFile(outputName);
            error  = CreateInheritedFile(errorName);

            bool success = false;

            SafeNativeMethods.PROCESS_INFORMATION pi = new SafeNativeMethods.PROCESS_INFORMATION();
            SafeProcessHandle   procSH       = new SafeProcessHandle();
            SafeThreadHandle    threadSH     = new SafeThreadHandle();
            SafeUserTokenHandle primaryToken = null;

            try {
                // Output the command line...
                StreamWriter sw = new StreamWriter(output, Encoding.UTF8);
                sw.Write(currentDir);
                sw.Write("> ");
                // 'true' command line is used in case the command line points to
                // a response file
                sw.WriteLine(trueCmdLine != null ? trueCmdLine : cmd);
                sw.WriteLine();
                sw.WriteLine();
                sw.Flush();

                NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO();

                si.cb = Marshal.SizeOf(si);
#if FEATURE_PAL
                si.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
#else //!FEATURE_PAL
                si.dwFlags     = NativeMethods.STARTF_USESTDHANDLES | NativeMethods.STARTF_USESHOWWINDOW;
                si.wShowWindow = NativeMethods.SW_HIDE;
#endif //!FEATURE_PAL
                si.hStdOutput = output.SafeFileHandle;
                si.hStdError  = error.SafeFileHandle;
                si.hStdInput  = new SafeFileHandle(UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);

                //
                // Prepare the environment
                //
#if PLATFORM_UNIX
                StringDictionary environment = new CaseSensitiveStringDictionary();
#else
                StringDictionary environment = new StringDictionary();
#endif // PLATFORM_UNIX

                // Add the current environment
                foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
                {
                    environment[(string)entry.Key] = (string)entry.Value;
                }

                // Add the flag to indicate restricted security in the process
                environment["_ClrRestrictSecAttributes"] = "1";

                #if DEBUG
                environment["OANOCACHE"] = "1";
                #endif

                // set up the environment block parameter
                byte[] environmentBytes = EnvironmentBlock.ToByteArray(environment, false);
                fixed(byte *environmentBytesPtr = environmentBytes)
                {
                    IntPtr environmentPtr = new IntPtr((void *)environmentBytesPtr);

                    if (userToken == null || userToken.IsInvalid)
                    {
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try {} finally {
                            success = NativeMethods.CreateProcess(
                                null,                              // String lpApplicationName,
                                new StringBuilder(cmd),            // String lpCommandLine,
                                null,                              // SECURITY_ATTRIBUTES lpProcessAttributes,
                                null,                              // SECURITY_ATTRIBUTES lpThreadAttributes,
                                true,                              // bool bInheritHandles,
                                0,                                 // int dwCreationFlags,
                                environmentPtr,                    // IntPtr lpEnvironment,
                                currentDir,                        // String lpCurrentDirectory,
                                si,                                // STARTUPINFO lpStartupInfo,
                                pi);                               // PROCESS_INFORMATION lpProcessInformation);
                            if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                            {
                                procSH.InitialSetHandle(pi.hProcess);
                            }
                            if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                            {
                                threadSH.InitialSetHandle(pi.hThread);
                            }
                        }
                    }
                    else
                    {
#if FEATURE_PAL
                        throw new NotSupportedException();
#else
                        success = SafeUserTokenHandle.DuplicateTokenEx(
                            userToken,
                            NativeMethods.TOKEN_ALL_ACCESS,
                            null,
                            NativeMethods.IMPERSONATION_LEVEL_SecurityImpersonation,
                            NativeMethods.TOKEN_TYPE_TokenPrimary,
                            out primaryToken
                            );


                        if (success)
                        {
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try {} finally {
                                success = NativeMethods.CreateProcessAsUser(
                                    primaryToken,                        // int token,
                                    null,                                // String lpApplicationName,
                                    cmd,                                 // String lpCommandLine,
                                    null,                                // SECURITY_ATTRIBUTES lpProcessAttributes,
                                    null,                                // SECURITY_ATTRIBUTES lpThreadAttributes,
                                    true,                                // bool bInheritHandles,
                                    0,                                   // int dwCreationFlags,
                                    new HandleRef(null, environmentPtr), // IntPtr lpEnvironment,
                                    currentDir,                          // String lpCurrentDirectory,
                                    si,                                  // STARTUPINFO lpStartupInfo,
                                    pi);                                 // PROCESS_INFORMATION lpProcessInformation);
                                if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                                {
                                    procSH.InitialSetHandle(pi.hProcess);
                                }
                                if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                                {
                                    threadSH.InitialSetHandle(pi.hThread);
                                }
                            }
                        }
#endif // !FEATURE_PAL
                    }
                }
            }
            finally {
                // Close the file handles
                if (!success && (primaryToken != null && !primaryToken.IsInvalid))
                {
                    primaryToken.Close();
                    primaryToken = null;
                }

                output.Close();
                error.Close();
            }

            if (success)
            {
                try {
                    bool signaled;
                    ProcessWaitHandle pwh = null;
                    try {
                        pwh      = new ProcessWaitHandle(procSH);
                        signaled = pwh.WaitOne(ProcessTimeOut, false);
                    } finally {
                        if (pwh != null)
                        {
                            pwh.Close();
                        }
                    }

                    // Check for timeout
                    if (!signaled)
                    {
                        throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT);
                    }

                    // Check the process's exit code
                    int status = NativeMethods.STILL_ACTIVE;
                    if (!NativeMethods.GetExitCodeProcess(procSH, out status))
                    {
                        throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error());
                    }

                    retValue = status;
                }
                finally {
                    procSH.Close();
                    threadSH.Close();
                    if (primaryToken != null && !primaryToken.IsInvalid)
                    {
                        primaryToken.Close();
                    }
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                if (err == NativeMethods.ERROR_NOT_ENOUGH_MEMORY)
                {
                    throw new OutOfMemoryException();
                }

                Win32Exception    win32Exception = new Win32Exception(err);
                ExternalException ex             = new ExternalException(SR.GetString(SR.ExecCantExec, cmd), win32Exception);
                throw ex;
            }

            return(retValue);
        }
        // ************************************************************************
        /// <summary>
        /// Only support existing exectuable (no association or dos command which have no executable like 'dir').
        /// But accept full path, partial path or no path where it will use regular system/user path.
        /// </summary>
        /// <param name="executablePath"></param>
        /// <param name="arguments"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        private ProcessWithOutputCaptureResult Execute(string executablePath, string arguments = null, int timeout = Timeout.Infinite)
        {
            ProcessWithOutputCaptureResult processWithOutputCaptureResult = null;

            using (Process process = new Process())
            {
                process.StartInfo.FileName        = executablePath;
                process.StartInfo.Arguments       = arguments;
                process.StartInfo.UseShellExecute = false;                 // required to redirect output to appropriate (output or error) process stream

                process.StartInfo.WindowStyle    = ProcessWindowStyle;
                process.StartInfo.CreateNoWindow = CreateWindow;

                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                _outputWaitHandle = new AutoResetEvent(false);
                _errorWaitHandle  = new AutoResetEvent(false);

                bool asyncReadStarted = false;

                try
                {
                    process.OutputDataReceived += ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  += ProcessOnErrorDataReceived;

                    process.Start();

                    // Here there is a race condition. See: https://connect.microsoft.com/VisualStudio/feedback/details/3119134/race-condition-in-process-asynchronous-output-stream-read

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    asyncReadStarted = true;

                    // See: ProcessStartInfo.RedirectStandardOutput Property:
                    //		https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Diagnostics.ProcessStartInfo.RedirectStandardOutput);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
                    // All 4 next lines should only be called when not using asynchronous read (process.BeginOutputReadLine() and process.BeginErrorReadLine())
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());

                    var waitHandles = new WaitHandle[1 + (AdditionalConditionToStopWaitingProcess == null ? 0 : 1)];

                    waitHandles[0] = new ProcessWaitHandle(process);
                    if (AdditionalConditionToStopWaitingProcess != null)
                    {
                        waitHandles[1] = AdditionalConditionToStopWaitingProcess;
                    }

                    bool hasSucceded = false;
                    int  waitResult  = WaitHandle.WaitAny(waitHandles, timeout);
                    if (waitResult == 1)                     // The wait has been interrrupted by an external event
                    {
                        if (IsAdditionalConditionToStopWaitingProcessShouldAlsoKill)
                        {
                            process.Kill();
                        }
                    }
                    else if (waitResult == 0)                     // Process has completed normally, no timeout or external event
                    {
                        // Ensure internal process code has completed like ensure to wait until stdout et stderr had been fully completed
                        hasSucceded = process.WaitForExit(timeout);

                        if (_outputWaitHandle.WaitOne(timeout) && _errorWaitHandle.WaitOne(timeout))
                        {
                            processWithOutputCaptureResult          = new ProcessWithOutputCaptureResult();
                            processWithOutputCaptureResult.ExitCode = process.ExitCode;
                            processWithOutputCaptureResult.Output   = _sbOutput.ToString();
                            processWithOutputCaptureResult.Error    = _sbError.ToString();
                        }
                    }
                    else                     // Process timeout
                    {
                        processWithOutputCaptureResult            = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.HasTimeout = true;
                    }
                }
                catch (Exception ex)
                {
                    if (ex.HResult == -2147467259)
                    {
                        processWithOutputCaptureResult           = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.Exception = new FileNotFoundException("File not found: " + executablePath, ex);
                    }
                    else
                    {
                        processWithOutputCaptureResult           = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.Exception = ex;
                    }
                }
                finally
                {
                    if (asyncReadStarted)
                    {
                        process.CancelOutputRead();
                        process.CancelErrorRead();
                    }

                    process.OutputDataReceived -= ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  -= ProcessOnOutputDataReceived;

                    _outputWaitHandle.Close();
                    _outputWaitHandle.Dispose();

                    _errorWaitHandle.Close();
                    _errorWaitHandle.Dispose();
                }
            }

            return(processWithOutputCaptureResult);
        }
Пример #18
0
 public ProcessExitMonitor(ProcessHandle processHandle)
 {
     _processWaitHandle = new ProcessWaitHandle(processHandle);
     ThreadPool.RegisterWaitForSingleObject(_processWaitHandle, HandleExited, null, -1, true);
 }
Пример #19
0
        }         // proc CreateProcessPipe

        public bool StartProcess()
        {
            try
            {
                if (IsProcessRunning)
                {
                    StopProcess();
                }

                Log.LogMsg(LogMsgType.Information, "Starte anwendung...");
                if (inputEncoding != null)
                {
                    Console.InputEncoding = inputEncoding;
                }

                SafeFileHandle hInput       = null;
                SafeFileHandle hOutput      = null;
                SafeFileHandle hError       = null;
                var            hEnvironment = default(GCHandle);
                using (var startupInfo = new NativeMethods.STARTUPINFO())
                    try
                    {
                        // Erzeuge die Befehlszeile
                        var sbCommand = new StringBuilder();

                        var fileName = Config.GetAttribute("filename", String.Empty);
                        if (!String.IsNullOrEmpty(fileName))
                        {
                            if (fileName.Length > 0 && fileName[0] == '"' && fileName[fileName.Length] == '"')
                            {
                                sbCommand.Append(fileName);
                            }
                            else
                            {
                                sbCommand.Append('"').Append(fileName).Append('"');
                            }
                        }

                        string sArguments = Config.GetAttribute("arguments", String.Empty);
                        if (!String.IsNullOrEmpty(sArguments))
                        {
                            sbCommand.Append(' ').Append(sArguments);
                        }
                        XElement arguments = Config.Element(xnArguments);
                        if (arguments != null && !String.IsNullOrEmpty(arguments.Value))
                        {
                            sbCommand.Append(' ').Append(arguments.Value);
                        }

                        if (sbCommand.Length == 0)
                        {
                            throw new ArgumentException("filename", "Keine Datei angegeben.");
                        }

                        // Working-Directory
                        var workingDirectory = Config.GetAttribute("workingDirectory", null);

                        // Soll der Prozess unter einem anderen Nutzer ausgeführt werden
                        var domain   = Config.GetAttribute("domain", null);
                        var userName = Config.GetAttribute("username", null);
                        var password = Config.GetAttribute("password", null);
                        if (!String.IsNullOrEmpty(userName))
                        {
                            if (!NativeMethods.LogonUser(userName, domain, password, Environment.UserInteractive ? NativeMethods.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE : NativeMethods.LOGON_TYPE.LOGON32_LOGON_SERVICE, NativeMethods.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hUser))
                            {
                                throw new Win32Exception();
                            }
                        }

                        // Erzeuge eine Environment für den Prozess
                        hEnvironment = GCHandle.Alloc(CreateEnvironment(hUser, userName, Config.GetAttribute("loadUserProfile", false)), GCHandleType.Pinned);

                        // Flags für den neuen Prozess
                        var flags = NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NEW_PROCESS_GROUP | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_SUSPENDED;

                        // Erzeuge die Startparameter
                        startupInfo.dwFlags = 0x00000100;
                        CreateProcessPipe(true, out hInput, out startupInfo.hStdInput);
                        CreateProcessPipe(false, out hOutput, out startupInfo.hStdOutput);
                        CreateProcessPipe(false, out hError, out startupInfo.hStdError);

                        NativeMethods.PROCESS_INFORMATION processinformation = new NativeMethods.PROCESS_INFORMATION();
                        try
                        {
                            if (hUser == IntPtr.Zero)
                            {
                                if (!NativeMethods.CreateProcess(null, sbCommand, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation))
                                {
                                    throw new Win32Exception();
                                }
                            }
                            else
                            {
                                if (!NativeMethods.CreateProcessAsUser(hUser, null, sbCommand, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation))
                                {
                                    throw new Win32Exception();
                                }
                            }

                            // Erzeuge das .net Prozess-Objekt
                            process = Process.GetProcessById(processinformation.dwProcessId);

                            // Erzeuge die Pipes
                            inputStream           = new StreamWriter(new FileStream(hInput, FileAccess.Write, 4096, false), inputEncoding ?? Console.InputEncoding);
                            inputStream.AutoFlush = true;
                            outputStream          = new StreamReader(new FileStream(hOutput, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding);
                            errorStream           = new StreamReader(new FileStream(hError, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding);

                            exitWaitHandle = new ProcessWaitHandle(processinformation.hProcess);
                            waitHandle     = ThreadPool.RegisterWaitForSingleObject(exitWaitHandle, ProcessExited, process, -1, true);

                            arOutputStream = procProcessLogLine.BeginInvoke(LogMsgType.Information, outputStream, null, outputStream);
                            arErrorStream  = procProcessLogLine.BeginInvoke(LogMsgType.Warning, errorStream, null, errorStream);

                            // Starte die Anwendung
                            NativeMethods.ResumeThread(processinformation.hThread);
                        }
                        finally
                        {
                            NativeMethods.CloseHandle(processinformation.hThread);
                        }
                    }
                    catch
                    {
                        if (hUser != IntPtr.Zero)
                        {
                            NativeMethods.CloseHandle(hUser);
                        }
                        if (hInput != null && !hInput.IsInvalid)
                        {
                            hInput.Close();
                        }
                        if (hOutput != null && !hOutput.IsInvalid)
                        {
                            hOutput.Close();
                        }
                        if (hError != null && !hError.IsInvalid)
                        {
                            hError.Close();
                        }

                        throw;
                    }
                    finally
                    {
                        if (hEnvironment.IsAllocated)
                        {
                            hEnvironment.Free();
                        }
                    }

                CallMemberDirect("ProcessStarted", new object[] { process }, throwExceptions: false);
                HttpRefreshProperties();

                return(true);
            }
            catch (Exception e)
            {
                Log.LogMsg(LogMsgType.Error, e.GetMessageString());
                return(false);
            }
        }         // proc StartProcess
Пример #20
0
        private void MonitorThread()
        {
            ProcessWaitHandle procWaitHandle = null;
            WaitHandle[] waitHandles;

            try
            {
                unsafe
                {
                    // Get pointers to shared memory objects.
                    ConsoleParams* consoleParams = (ConsoleParams*)_consoleParams.Get();
                    CONSOLE_SCREEN_BUFFER_INFO* consoleScreenInfo = (CONSOLE_SCREEN_BUFFER_INFO*)
                        _consoleScreenInfo.Get();
                    ConsoleBufferInfo* consoleBufferInfo = (ConsoleBufferInfo*)_consoleBufferInfo.Get();

                    // Keep waiting for new events until process has exitted or thread is aborted.
                    procWaitHandle = new ProcessWaitHandle(_procSafeWaitHandle);
                    waitHandles = new WaitHandle[] { procWaitHandle, _consoleBufferInfo.RequestEvent };

                    // Loop until console has exitted.
                    while (WaitHandle.WaitAny(waitHandles) > 0)
                    {
                        // Get current window and buffer size.
                        int columns = consoleScreenInfo->srWindow.Right - consoleScreenInfo->srWindow.Left + 1;
                        int rows = consoleScreenInfo->srWindow.Bottom - consoleScreenInfo->srWindow.Top + 1;
                        int bufferColumns = consoleScreenInfo->dwSize.X;
                        int bufferRows = consoleScreenInfo->dwSize.Y;

                        // Check if window size has changed.
                        if (consoleParams->Columns != columns || consoleParams->Rows != rows)
                        {
                            consoleParams->Columns = columns;
                            consoleParams->Rows = rows;

                            // Raise event, window has been resized.
                            if (ConsoleWindowResized != null) ConsoleWindowResized(this, new EventArgs());
                        }

                        // Check if buffer size has changed.
                        if ((consoleParams->BufferColumns != 0
                            && consoleParams->BufferColumns != bufferColumns) ||
                            (consoleParams->BufferRows != 0 && consoleParams->BufferRows != bufferRows))
                        {
                            consoleParams->BufferColumns = bufferColumns;
                            consoleParams->BufferRows = bufferRows;

                            // Raise event, buffer has been resized.
                            if (ConsoleBufferResized != null) ConsoleBufferResized(this, new EventArgs());
                        }

                        if (consoleBufferInfo->NewDataFound || consoleBufferInfo->CursorPositionChanged)
                        {
                            // Raise event, console has sent new data.
                            if (ConsoleNewData != null) ConsoleNewData(this, new EventArgs());

                            // Check if new data was found.
                            if (consoleBufferInfo->NewDataFound)
                            {
                                // Raise event, buffer data has changed.
                                if (ConsoleBufferChanged != null) ConsoleBufferChanged(this, new EventArgs());
                            }

                            // Check if cursor posistion has changed.
                            if (consoleBufferInfo->CursorPositionChanged)
                            {
                                // Raise event, cursor position has changed.
                                if (ConsoleCursorPositionChanged != null) ConsoleCursorPositionChanged(this,
                                    new EventArgs());
                            }
                        }
                    }
                }
            }
            catch (ThreadAbortException)
            {
            }
            finally
            {
                if (procWaitHandle != null) procWaitHandle.Close();

                // Raise event.
                if (ConsoleClosed != null) ConsoleClosed(this, new EventArgs());
            }
        }
        private static unsafe int ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine)
        {
            IntSecurity.UnmanagedCode.Demand();
            if ((outputName == null) || (outputName.Length == 0))
            {
                outputName = tempFiles.AddExtension("out");
            }
            if ((errorName == null) || (errorName.Length == 0))
            {
                errorName = tempFiles.AddExtension("err");
            }
            FileStream stream  = CreateInheritedFile(outputName);
            FileStream stream2 = CreateInheritedFile(errorName);
            bool       flag    = false;

            Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation = new Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION();
            Microsoft.Win32.SafeHandles.SafeProcessHandle         processHandle        = new Microsoft.Win32.SafeHandles.SafeProcessHandle();
            Microsoft.Win32.SafeHandles.SafeThreadHandle          handle2 = new Microsoft.Win32.SafeHandles.SafeThreadHandle();
            SafeUserTokenHandle hNewToken = null;

            try
            {
                Microsoft.Win32.NativeMethods.STARTUPINFO startupinfo;
                StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
                writer.Write(currentDir);
                writer.Write("> ");
                writer.WriteLine((trueCmdLine != null) ? trueCmdLine : cmd);
                writer.WriteLine();
                writer.WriteLine();
                writer.Flush();
                startupinfo = new Microsoft.Win32.NativeMethods.STARTUPINFO {
                    cb          = Marshal.SizeOf(startupinfo),
                    dwFlags     = 0x101,
                    wShowWindow = 0,
                    hStdOutput  = stream.SafeFileHandle,
                    hStdError   = stream2.SafeFileHandle,
                    hStdInput   = new SafeFileHandle(Microsoft.Win32.UnsafeNativeMethods.GetStdHandle(-10), false)
                };
                StringDictionary sd = new StringDictionary();
                foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
                {
                    sd[(string)entry.Key] = (string)entry.Value;
                }
                sd["_ClrRestrictSecAttributes"] = "1";
                byte[] buffer = EnvironmentBlock.ToByteArray(sd, false);
                try
                {
                    fixed(byte *numRef = buffer)
                    {
                        IntPtr lpEnvironment = new IntPtr((void *)numRef);

                        if ((userToken == null) || userToken.IsInvalid)
                        {
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try
                            {
                                goto Label_0325;
                            }
                            finally
                            {
                                flag = Microsoft.Win32.NativeMethods.CreateProcess(null, new StringBuilder(cmd), null, null, true, 0, lpEnvironment, currentDir, startupinfo, lpProcessInformation);
                                if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE))
                                {
                                    processHandle.InitialSetHandle(lpProcessInformation.hProcess);
                                }
                                if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE))
                                {
                                    handle2.InitialSetHandle(lpProcessInformation.hThread);
                                }
                            }
                        }
                        flag = SafeUserTokenHandle.DuplicateTokenEx(userToken, 0xf01ff, null, 2, 1, out hNewToken);
                        if (flag)
                        {
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try
                            {
                            }
                            finally
                            {
                                flag = Microsoft.Win32.NativeMethods.CreateProcessAsUser(hNewToken, null, cmd, null, null, true, 0, new HandleRef(null, lpEnvironment), currentDir, startupinfo, lpProcessInformation);
                                if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE))
                                {
                                    processHandle.InitialSetHandle(lpProcessInformation.hProcess);
                                }
                                if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE))
                                {
                                    handle2.InitialSetHandle(lpProcessInformation.hThread);
                                }
                            }
                        }
                    }
                }
                finally
                {
                    numRef = null;
                }
            }
            finally
            {
                if ((!flag && (hNewToken != null)) && !hNewToken.IsInvalid)
                {
                    hNewToken.Close();
                    hNewToken = null;
                }
                stream.Close();
                stream2.Close();
            }
Label_0325:
            if (flag)
            {
                try
                {
                    bool flag2;
                    ProcessWaitHandle handle4 = null;
                    try
                    {
                        handle4 = new ProcessWaitHandle(processHandle);
                        flag2   = handle4.WaitOne(0x927c0, false);
                    }
                    finally
                    {
                        if (handle4 != null)
                        {
                            handle4.Close();
                        }
                    }
                    if (!flag2)
                    {
                        throw new ExternalException(SR.GetString("ExecTimeout", new object[] { cmd }), 0x102);
                    }
                    int exitCode = 0x103;
                    if (!Microsoft.Win32.NativeMethods.GetExitCodeProcess(processHandle, out exitCode))
                    {
                        throw new ExternalException(SR.GetString("ExecCantGetRetCode", new object[] { cmd }), Marshal.GetLastWin32Error());
                    }
                    return(exitCode);
                }
                finally
                {
                    processHandle.Close();
                    handle2.Close();
                    if ((hNewToken != null) && !hNewToken.IsInvalid)
                    {
                        hNewToken.Close();
                    }
                }
            }
            int error = Marshal.GetLastWin32Error();

            if (error == 8)
            {
                throw new OutOfMemoryException();
            }
            Win32Exception    inner      = new Win32Exception(error);
            ExternalException exception2 = new ExternalException(SR.GetString("ExecCantExec", new object[] { cmd }), inner);

            throw exception2;
        }
Пример #22
0
        private static void StartProcessAsUser(ProcessStartInfo psi)
        {
            string       username        = psi.UserName;
            string       domain          = psi.Domain;
            SecureString password        = psi.Password;
            string       commandLinePath = "\"" + psi.FileName + "\" " + psi.Arguments;
            string       cwd             = psi.WorkingDirectory;

            IntPtr Token      = IntPtr.Zero;
            IntPtr DupedToken = IntPtr.Zero;

            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();

            sa.bInheritHandle       = false;
            sa.Length               = Marshal.SizeOf(sa);
            sa.lpSecurityDescriptor = IntPtr.Zero;

            if (string.IsNullOrEmpty(domain))
            {
                domain = ".";
            }

            IntPtr passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password ?? new SecureString());

            try
            {
                if (!LogonUser(username, domain, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref Token))
                {
                    var ex = new Win32Exception();
                    CloseHandle(Token);
                    throw ex;
                }
            }
            finally
            {
                Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);
            }

            const uint GENERIC_ALL = 0x10000000;

            const int SecurityImpersonation = 2;
            const int TokenType             = 1;

            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

            try
            {
                if (!DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken))
                {
                    throw new Win32Exception();
                }

                STARTUPINFO si = new STARTUPINFO();
                si.cb = Marshal.SizeOf(si);

                if (!CreateProcessAsUser(DupedToken, null, commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, cwd, ref si, out pi))
                {
                    throw new Win32Exception();
                }

                uint exitCode = 0;
                bool timeout  = false;

                ProcessWaitHandle waitable = new ProcessWaitHandle(pi.hProcess);
                if (!waitable.WaitOne(timeoutToKill * 1000))
                {
                    timeout = true;
                    using (Process process = Process.GetProcessById((int)pi.dwProcessId))
                        if (process != null)
                        {
                            process.Kill();
                        }
                }
                else
                {
                    if (!GetExitCodeProcess(pi.hProcess, out exitCode))
                    {
                        throw new Win32Exception();
                    }
                }

                ValidateExitCode(timeout ? -10 : (int)exitCode);
            }
            finally
            {
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);

                CloseHandle(DupedToken);
                CloseHandle(Token);
            }
        }