예제 #1
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
예제 #2
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