} // 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
} // 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