public void Run() { IntPtr primaryToken = GetCurrentUserToken(); if (primaryToken == IntPtr.Zero) { return; } NativeMethods.STARTUPINFO StartupInfo = new NativeMethods.STARTUPINFO(); processInfo_ = new NativeMethods.PROCESS_INFORMATION(); StartupInfo.cb = Marshal.SizeOf(StartupInfo); NativeMethods.SECURITY_ATTRIBUTES Security1 = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES Security2 = new NativeMethods.SECURITY_ATTRIBUTES(); string command = "\"" + processPath_ + "\""; if ((arguments_ != null) && (arguments_.Length != 0)) { command += " " + arguments_; } IntPtr lpEnvironment = IntPtr.Zero; bool resultEnv = NativeMethods.CreateEnvironmentBlock(out lpEnvironment, primaryToken, false); if (resultEnv != true) { int nError = NativeMethods.GetLastError(); } NativeMethods.CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, NativeMethods.CREATE_NO_WINDOW | NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_); NativeMethods.DestroyEnvironmentBlock(lpEnvironment); NativeMethods.CloseHandle(primaryToken); }
private static int CreateProcessAsUser(string executablePath, string commandLine, string workingDirectory, IntPtr userToken) { using (AutoDisposeHandle environmentVariables = CreateEnvironmentBlock(userToken)) { if (environmentVariables == null) { return(-1); } NativeMethods.STARTUPINFO startupInformation = new NativeMethods.STARTUPINFO(); startupInformation.length = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); startupInformation.desktop = "Winsta0\\Default"; startupInformation.showWindow = (short)NativeMethods.WindowShowStyle.ShowNoActivate; NativeMethods.PROCESS_INFORMATION processInformation = new NativeMethods.PROCESS_INFORMATION(); try { bool result = NativeMethods.CreateProcessAsUser ( userToken, executablePath, commandLine, IntPtr.Zero, IntPtr.Zero, false, (uint)(NativeMethods.CreateProcessFlags.DETACHED_PROCESS | NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT), environmentVariables, workingDirectory, ref startupInformation, ref processInformation ); if (!result) { Win32Helper.ThrowLastWin32Error("Unable to start process \"" + executablePath + "\""); } return(processInformation.processID); } finally { if (processInformation.processHandle != IntPtr.Zero) { try { NativeMethods.CloseHandle(processInformation.processHandle); } catch { } } if (processInformation.threadHandle != IntPtr.Zero) { try { NativeMethods.CloseHandle(processInformation.threadHandle); } catch { } } } } }
public static void LaunchProcessAsUser(string app, string args, IntPtr token) { IntPtr primaryToken = IntPtr.Zero; var securityAttrs = new NativeMethods.SECURITY_ATTRIBUTES(); //ZeroMemory(sa, (uint)Marshal.SizeOf(sa)); securityAttrs.nLength = (uint)Marshal.SizeOf(securityAttrs); securityAttrs.bInheritHandle = false; securityAttrs.lpSecurityDescriptor = IntPtr.Zero; var startupInfo = new NativeMethods.STARTUPINFO(); //ZeroMemory(si, (uint)Marshal.SizeOf(si)); startupInfo.cb = (uint)Marshal.SizeOf(startupInfo); bool retdup = NativeMethods.DuplicateTokenEx(token, NativeMethods.TOKEN_ASSIGN_PRIMARY | NativeMethods.TOKEN_DUPLICATE | NativeMethods.TOKEN_QUERY, ref securityAttrs, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)NativeMethods.TOKEN_TYPE.TokenPrimary, ref primaryToken); if (!retdup) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to duplicate the current user's token."); } try { IntPtr UserEnvironment; bool retenviron = NativeMethods.CreateEnvironmentBlock(out UserEnvironment, token, false); if (!retenviron) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to create user environment."); } try { string cmd = $"\"{app}\" {args}"; bool retimper = NativeMethods.CreateProcessAsUser(primaryToken, null, cmd, ref securityAttrs, ref securityAttrs, false, NativeMethods.CREATE_UNICODE_ENVIRONMENT, UserEnvironment, null, ref startupInfo, out var processInfo); if (!retimper) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to impersonate. Command was: " + cmd); } NativeMethods.CloseHandle(processInfo.hThread); NativeMethods.CloseHandle(processInfo.hProcess); } finally { NativeMethods.DestroyEnvironmentBlock(UserEnvironment); } } finally { NativeMethods.CloseHandle(primaryToken); } }
/// <summary> /// Initializes a new instance of the BrokerProcess class /// </summary> /// <param name="brokerFileName">indicating the broker file name</param> /// <param name="environments">indicating the environments</param> public BrokerProcess(string brokerFileName, NameValueConfigurationCollection environments) { this.startupInfo = new NativeMethods.STARTUPINFO(); this.startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); this.processInfo = new NativeMethods.PROCESS_INFORMATION(); string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string fileName = Path.Combine(path, brokerFileName); StringBuilder commandLine = null; TraceHelper.TraceEvent(TraceEventType.Information, "[BrokerProcess] Start broker process, FileName = {0}", fileName); IntPtr environmentPtr; if (environments != null) { this.environmentHandle = GCHandle.Alloc(ToByteArray(environments), GCHandleType.Pinned); environmentPtr = this.environmentHandle.AddrOfPinnedObject(); } else { environmentPtr = IntPtr.Zero; } if (!NativeMethods.CreateProcess(fileName, commandLine, IntPtr.Zero, IntPtr.Zero, true, creationFlags, environmentPtr, path, ref this.startupInfo, out this.processInfo)) { int errorCode = Marshal.GetLastWin32Error(); TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed: {0}", errorCode); ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, errorCode.ToString()); } SafeWaitHandle handle = new SafeWaitHandle(this.processInfo.hProcess, false); if (handle.IsClosed || handle.IsInvalid) { TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed because the process handle is invalid or closed."); ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, "Handle is invalid or closed"); } string uniqueWaitHandleName = BuildUniqueWaitHandle(this.Id, out this.readyWaitHandle); WaitOrTimerCallback brokerProcessReadyCallback = new ThreadHelper <object>(new WaitOrTimerCallback(this.BrokerProcessReadyCallback)).WaitOrTimerCallbackRoot; WaitOrTimerCallback processExitCallback = new ThreadHelper <object>(new WaitOrTimerCallback(this.ProcessExitCallback)).WaitOrTimerCallbackRoot; this.exitWaitHandle = new ManualResetEvent(false); this.exitWaitHandle.SafeWaitHandle = handle; // Register broker process exit callback ThreadPool.RegisterWaitForSingleObject(this.exitWaitHandle, processExitCallback, null, -1, true); // Register callback to be raised when broker process opened service host and is ready to initialize. ThreadPool.RegisterWaitForSingleObject(this.readyWaitHandle, brokerProcessReadyCallback, null, readyTimeout, true); }
/// <summary> /// ユーザーセッションでコマンドを実行する /// </summary> /// <param name="commandline">実行したいコマンド</param> /// <exception cref="InvalidOperationException"></exception> public static void CreateProcessAsUser(string commandline) { var sessionId = NativeMethods.WTSGetActiveConsoleSessionId(); IntPtr hPToken = IntPtr.Zero; var hUserTokenDup = IntPtr.Zero; var ret = NativeMethods.WTSQueryUserToken(sessionId, out hPToken); var sa = new NativeMethods.SECURITY_ATTRIBUTES(); sa.nLength = Marshal.SizeOf(sa); if (!NativeMethods.DuplicateTokenEx(hPToken, NativeMethods.TOKEN_ALL_ACCESS, ref sa, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, NativeMethods.TOKEN_TYPE.TokenPrimary, out hUserTokenDup)) { NativeMethods.CloseHandle(hPToken); throw new InvalidOperationException(); } var si = new NativeMethods.STARTUPINFO() { cb = Marshal.SizeOf(sa), lpDesktop = @"winsta0\default", wShowWindow = 0,//SW_HIDE dwFlags = NativeMethods.STARTF_USESHOWWINDOW, }; var creationFlags = NativeMethods.CREATE_UNICODE_ENVIRONMENT; var env = IntPtr.Zero; // アクティブユーザのセッションを設定します var ret2 = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenSessionId, ref sessionId, sizeof(NativeMethods.TOKEN_INFORMATION_CLASS)); // 環境変数を設定 if (!NativeMethods.CreateEnvironmentBlock(out env, hUserTokenDup, true)) { env = IntPtr.Zero; } NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.CreateProcessAsUser(hUserTokenDup, IntPtr.Zero, commandline, IntPtr.Zero, IntPtr.Zero, false, creationFlags, env, IntPtr.Zero, ref si, out pi); NativeMethods.DestroyEnvironmentBlock(env); }
private void StartProcess() { uint id = (uint)NativeMethods.WTSGetActiveConsoleSessionId(); IntPtr token; bool ok = NativeMethods.WTSQueryUserToken(id, out token); NativeMethods.SECURITY_ATTRIBUTES security = new NativeMethods.SECURITY_ATTRIBUTES(); security.nLength = Marshal.SizeOf(typeof(NativeMethods.SECURITY_ATTRIBUTES)); if (!NativeMethods.DuplicateTokenEx(token, NativeMethods.ACCESS_MASK.MAXIMUM_ALLOWED, ref security, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, NativeMethods.TOKEN_TYPE.TokenPrimary, out tokenCopy)) { throw new Exception("Can't create duplicate token"); } if (ok) { NativeMethods.CloseHandle(token); } if (!NativeMethods.CreateEnvironmentBlock(out environment, tokenCopy, false)) { throw new Exception("Can't create environment block"); } security = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO(); startupInfo.dwFlags = 1; startupInfo.wShowWindow = 1; startupInfo.lpDesktop = "winsta0\\default"; string location = Assembly.GetEntryAssembly().Location; StringBuilder cmd = new StringBuilder(); cmd.AppendFormat("\"{0}\" {1}", location, EMBEDDING); string directory = Path.GetDirectoryName(location); if (!NativeMethods.CreateProcessAsUser(tokenCopy, null, cmd, ref security, ref security, false, NativeMethods.CREATE_UNICODE_ENVIRONMENT, environment, directory, ref startupInfo, out processInfo)) { throw new Exception("Can't create process as a user. Error: " + Marshal.GetLastWin32Error()); } }
public void Start() { NativeMethods.STARTUPINFO startInfo = default(NativeMethods.STARTUPINFO); startInfo.cb = Marshal.SizeOf(startInfo); startInfo.dwFlags = NativeMethods.STARTF_USE_SHOWWINDOW; startInfo.wShowWindow = NativeMethods.SW_HIDE; string commandLine = String.Format(ProxyProcessManager.POWERSHELL_COMMAND_LINE, Assembly.GetExecutingAssembly().Location, this.commandPipeName); NativeMethods.PROCESS_INFORMATION procInfo; if (!NativeMethods.CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, false, NativeMethods.CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref startInfo, out procInfo)) { throw new Win32Exception(); } NativeMethods.CloseHandle(procInfo.hProcess); NativeMethods.CloseHandle(procInfo.hThread); this.proxyProcess = Process.GetProcessById(procInfo.dwProcessId); this.commandPipe.WaitForConnection(); }
/// <include file='doc\Executor.uex' path='docs/doc[@for="Executor.ExecWaitWithCapture3"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> internal static int ExecWaitWithCapture(IntPtr userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine) { IntSecurity.UnmanagedCode.Demand(); IntPtr output; IntPtr 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; NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); IntPtr primaryToken = IntPtr.Zero; GCHandle environmentHandle = new GCHandle(); try { // Output the command line... // Make sure the FileStream doesn't own the handle FileStream outputStream = new FileStream(output, FileAccess.ReadWrite, false /*ownsHandle*/); StreamWriter sw = new StreamWriter(outputStream, 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(); outputStream.Close(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; si.hStdOutput = output; si.hStdError = error; si.hStdInput = UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE); // // Prepare the environment // Hashtable environment = new Hashtable(); // Add the current environment foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) { environment.Add((string)entry.Key, (string)entry.Value); } // Add the flag to indicate restricted security in the process environment.Add("_ClrRestrictSecAttributes", "1"); // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; byte[] environmentBytes = EnvironmentToByteArray(environment); environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned); environmentPtr = environmentHandle.AddrOfPinnedObject(); if (userToken == IntPtr.Zero) { success = UnsafeNativeMethods.CreateProcess( null, // String lpApplicationName, new StringBuilder(cmd), // String lpCommandLine, null, // SECURITY_ATTRIBUTES lpProcessAttributes, null, // SECURITY_ATTRIBUTES lpThreadAttributes, true, // bool bInheritHandles, 0, // int dwCreationFlags, environmentPtr, // int lpEnvironment, currentDir, // String lpCurrentDirectory, si, // STARTUPINFO lpStartupInfo, pi); // PROCESS_INFORMATION lpProcessInformation); } else { throw new NotSupportedException(); } } finally { // free environment block if (environmentHandle.IsAllocated) { environmentHandle.Free(); } // Close the file handles UnsafeNativeMethods.CloseHandle(output); UnsafeNativeMethods.CloseHandle(error); } if (success) { try { int ret = SafeNativeMethods.WaitForSingleObject(pi.hProcess, ProcessTimeOut); // Check for timeout if (ret == NativeMethods.WAIT_TIMEOUT) { throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT); } if (ret != NativeMethods.WAIT_OBJECT_0) { throw new ExternalException(SR.GetString(SR.ExecBadreturn, cmd), Marshal.GetLastWin32Error()); } // Check the process's exit code int status = NativeMethods.STILL_ACTIVE; if (!UnsafeNativeMethods.GetExitCodeProcess(pi.hProcess, ref status)) { throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error()); } retValue = status; } finally { UnsafeNativeMethods.CloseHandle(pi.hThread); UnsafeNativeMethods.CloseHandle(pi.hProcess); if (primaryToken != IntPtr.Zero) { UnsafeNativeMethods.CloseHandle(primaryToken); } } } else { throw new ExternalException(SR.GetString(SR.ExecCantExec, cmd), Marshal.GetLastWin32Error()); } return(retValue); }
private bool StartWithCreateProcess(ProcessStartInfo startInfo) { if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) { throw new InvalidOperationException("StandardOutputEncodingNotAllowed"); } if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) { throw new InvalidOperationException("StandardErrorEncodingNotAllowed"); } StringBuilder stringBuilder = Process2.BuildCommandLine(startInfo.FileName, startInfo.Arguments); NativeMethods.STARTUPINFO sTARTUPINFO = new NativeMethods.STARTUPINFO(); SafeNativeMethods.PROCESS_INFORMATION pROCESS_INFORMATION = new SafeNativeMethods.PROCESS_INFORMATION(); SafeProcessHandle safeProcessHandle = new SafeProcessHandle(); SafeThreadHandle safeThreadHandle = new SafeThreadHandle(); int num = 0; SafeFileHandle handle = null; SafeFileHandle handle2 = null; SafeFileHandle handle3 = null; GCHandle gCHandle = default(GCHandle); lock (Process2.s_CreateProcessLock) { try { if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { if (startInfo.RedirectStandardInput) { CreatePipe(out handle, out sTARTUPINFO.hStdInput, true); } else { sTARTUPINFO.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(-10), false); } if (startInfo.RedirectStandardOutput) { CreatePipe(out handle2, out sTARTUPINFO.hStdOutput, false); } else { sTARTUPINFO.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(-11), false); } if (startInfo.RedirectStandardError) { CreatePipe(out handle3, out sTARTUPINFO.hStdError, false); } else { sTARTUPINFO.hStdError = sTARTUPINFO.hStdOutput; } sTARTUPINFO.dwFlags = 256; } int num2 = 0; if (startInfo.CreateNoWindow) { num2 |= 134217728; } IntPtr intPtr = (IntPtr)0; //if (startInfo.environmentVariables != null) //{ // bool unicode = false; // if (ProcessManager.IsNt) // { // num2 |= 1024; // unicode = true; // } // byte[] value = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode); // gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); // intPtr = gCHandle.AddrOfPinnedObject(); //} string text = startInfo.WorkingDirectory; if (text == string.Empty) { text = Environment.CurrentDirectory; } bool flag2; //if (startInfo.UserName.Length != 0) //{ // NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0; // if (startInfo.LoadUserProfile) // { // logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE; // } // IntPtr intPtr2 = IntPtr.Zero; // try // { // if (startInfo.Password == null) // { // intPtr2 = Marshal.StringToCoTaskMemUni(string.Empty); // } // else // { // intPtr2 = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); // } // RuntimeHelpers.PrepareConstrainedRegions(); // try // { // } // finally // { // flag2 = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, intPtr2, logonFlags, null, stringBuilder, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION); // if (!flag2) // { // num = Marshal.GetLastWin32Error(); // } // if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE) // { // safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess); // } // if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE) // { // safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread); // } // } // if (flag2) // { // goto IL_3B9; // } // if (num == 193 || num == 216) // { // throw new Win32Exception(num, SR.GetString("InvalidApplication")); // } // throw new Win32Exception(num); // } // finally // { // if (intPtr2 != IntPtr.Zero) // { // Marshal.ZeroFreeCoTaskMemUnicode(intPtr2); // } // } //} RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { flag2 = NativeMethods.CreateProcess(null, stringBuilder, null, null, true, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION); if (!flag2) { num = Marshal.GetLastWin32Error(); } if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE) { safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess); } if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE) { safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread); } } if (!flag2) { if (num == 193 || num == 216) { throw new Win32Exception(num, "InvalidApplication"); } throw new Win32Exception(num); } } finally { if (gCHandle.IsAllocated) { gCHandle.Free(); } sTARTUPINFO.Dispose(); } } if (startInfo.RedirectStandardInput) { standardInput = new StreamWriter(new FileStream(handle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096); standardInput.AutoFlush = true; } if (startInfo.RedirectStandardOutput) { Encoding encoding = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding; standardOutput = new StreamReader(new FileStream(handle2, FileAccess.Read, 4096, false), encoding, true, 4096); } if (startInfo.RedirectStandardError) { Encoding encoding2 = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding; standardError = new StreamReader(new FileStream(handle3, FileAccess.Read, 4096, false), encoding2, true, 4096); } bool result = false; if (!safeProcessHandle.IsInvalid) { SetProcessHandle(safeProcessHandle); SetProcessId(pROCESS_INFORMATION.dwProcessId); safeThreadHandle.Close(); result = true; } return(result); }
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); si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; 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.Add((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, // int 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 { throw new NotSupportedException(); } } } finally { // Close the file handles if (!success && (primaryToken != null && !primaryToken.IsInvalid)) { primaryToken.Close(); primaryToken = null; } output.Close(); error.Close(); } if (success) { try { int ret = NativeMethods.WaitForSingleObject(procSH, ProcessTimeOut); // Check for timeout if (ret == NativeMethods.WAIT_TIMEOUT) { throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT); } if (ret != NativeMethods.WAIT_OBJECT_0) { throw new ExternalException(SR.GetString(SR.ExecBadreturn, cmd), Marshal.GetLastWin32Error()); } // 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 { throw new ExternalException(SR.GetString(SR.ExecCantExec, cmd), Marshal.GetLastWin32Error()); } return(retValue); }
private bool StartWithCreateProcess(ProcessStartInfo startInfo) { if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput) { throw new InvalidOperationException("StandardOutputEncodingNotAllowed"); } if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError) { throw new InvalidOperationException("StandardErrorEncodingNotAllowed"); } StringBuilder stringBuilder = Process2.BuildCommandLine(startInfo.FileName, startInfo.Arguments); NativeMethods.STARTUPINFO sTARTUPINFO = new NativeMethods.STARTUPINFO(); SafeNativeMethods.PROCESS_INFORMATION pROCESS_INFORMATION = new SafeNativeMethods.PROCESS_INFORMATION(); SafeProcessHandle safeProcessHandle = new SafeProcessHandle(); SafeThreadHandle safeThreadHandle = new SafeThreadHandle(); int num = 0; SafeFileHandle handle = null; SafeFileHandle handle2 = null; SafeFileHandle handle3 = null; GCHandle gCHandle = default(GCHandle); lock (Process2.s_CreateProcessLock) { try { if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { if (startInfo.RedirectStandardInput) { CreatePipe(out handle, out sTARTUPINFO.hStdInput, true); } else { sTARTUPINFO.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(-10), false); } if (startInfo.RedirectStandardOutput) { CreatePipe(out handle2, out sTARTUPINFO.hStdOutput, false); } else { sTARTUPINFO.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(-11), false); } if (startInfo.RedirectStandardError) { CreatePipe(out handle3, out sTARTUPINFO.hStdError, false); } else { sTARTUPINFO.hStdError = sTARTUPINFO.hStdOutput; } sTARTUPINFO.dwFlags = 256; } int num2 = 0; if (startInfo.CreateNoWindow) { num2 |= 134217728; } IntPtr intPtr = (IntPtr)0; //if (startInfo.environmentVariables != null) //{ // bool unicode = false; // if (ProcessManager.IsNt) // { // num2 |= 1024; // unicode = true; // } // byte[] value = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode); // gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); // intPtr = gCHandle.AddrOfPinnedObject(); //} string text = startInfo.WorkingDirectory; if (text == string.Empty) { text = Environment.CurrentDirectory; } bool flag2; //if (startInfo.UserName.Length != 0) //{ // NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0; // if (startInfo.LoadUserProfile) // { // logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE; // } // IntPtr intPtr2 = IntPtr.Zero; // try // { // if (startInfo.Password == null) // { // intPtr2 = Marshal.StringToCoTaskMemUni(string.Empty); // } // else // { // intPtr2 = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); // } // RuntimeHelpers.PrepareConstrainedRegions(); // try // { // } // finally // { // flag2 = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, intPtr2, logonFlags, null, stringBuilder, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION); // if (!flag2) // { // num = Marshal.GetLastWin32Error(); // } // if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE) // { // safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess); // } // if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE) // { // safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread); // } // } // if (flag2) // { // goto IL_3B9; // } // if (num == 193 || num == 216) // { // throw new Win32Exception(num, SR.GetString("InvalidApplication")); // } // throw new Win32Exception(num); // } // finally // { // if (intPtr2 != IntPtr.Zero) // { // Marshal.ZeroFreeCoTaskMemUnicode(intPtr2); // } // } //} RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { flag2 = NativeMethods.CreateProcess(null, stringBuilder, null, null, true, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION); if (!flag2) { num = Marshal.GetLastWin32Error(); } if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE) { safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess); } if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE) { safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread); } } if (!flag2) { if (num == 193 || num == 216) { throw new Win32Exception(num, "InvalidApplication"); } throw new Win32Exception(num); } } finally { if (gCHandle.IsAllocated) { gCHandle.Free(); } sTARTUPINFO.Dispose(); } } if (startInfo.RedirectStandardInput) { standardInput = new StreamWriter(new FileStream(handle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096); standardInput.AutoFlush = true; } if (startInfo.RedirectStandardOutput) { Encoding encoding = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding; standardOutput = new StreamReader(new FileStream(handle2, FileAccess.Read, 4096, false), encoding, true, 4096); } if (startInfo.RedirectStandardError) { Encoding encoding2 = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding; standardError = new StreamReader(new FileStream(handle3, FileAccess.Read, 4096, false), encoding2, true, 4096); } bool result = false; if (!safeProcessHandle.IsInvalid) { SetProcessHandle(safeProcessHandle); SetProcessId(pROCESS_INFORMATION.dwProcessId); safeThreadHandle.Close(); result = true; } return result; }
public static Win32Process StartProcessAsUser(WindowsIdentity winIdentity, string applicationName, string commandLine, string workingDirectory, Win32NativeEnvironmentBlock environment, out Stream stdin, out Stream stdout, out Stream stderror) { NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); /* * When a process is started using CreateProcessAsUser function, the process will be started into a windowstation * and desktop combination based on the value of lpDesktop in the STARTUPINFO structure parameter: * lpDesktop = "<windowsta>\<desktop>"; the system will try to start the process into that windowstation and desktop. * lpDesktop = NULL; the system will try to use the same windowstation and desktop as the calling process if the system is associated with the interactive windowstation. * lpDesktop = <somevalue>; the system will create a new windowstation and desktop that you cannot see. * lpDesktop = ""; it will either create a new windowstation and desktop that you cannot see, or if one has been created by means of a prior call by using the same access token, the existing windowstation and desktop will be used. */ si.lpDesktop = ""; IntPtr stdinRead, stdinWrite, stdoutRead, stdoutWrite, stderrorRead, stderrorWrite; NativeMethods.SECURITY_ATTRIBUTES sa = default(NativeMethods.SECURITY_ATTRIBUTES); sa.nLength = Marshal.SizeOf(sa); sa.lpSecurityDescriptor = IntPtr.Zero; sa.bInheritHandle = true; if (!NativeMethods.CreatePipe(out stdinRead, out stdinWrite, ref sa, 0)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.SetHandleInformation(stdinWrite, NativeMethods.HANDLE_FLAGS.INHERIT, NativeMethods.HANDLE_FLAGS.None)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.CreatePipe(out stdoutRead, out stdoutWrite, ref sa, 0)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.SetHandleInformation(stdoutRead, NativeMethods.HANDLE_FLAGS.INHERIT, NativeMethods.HANDLE_FLAGS.None)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.CreatePipe(out stderrorRead, out stderrorWrite, ref sa, 0)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!NativeMethods.SetHandleInformation(stderrorRead, NativeMethods.HANDLE_FLAGS.INHERIT, NativeMethods.HANDLE_FLAGS.None)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; si.hStdInput = stdinRead; si.hStdOutput = stdoutWrite; si.hStdError = stderrorWrite; NativeMethods.SECURITY_ATTRIBUTES processAttr = CreateSecurityAttributes(winIdentity == null ? WellKnownSidType.AuthenticatedUserSid : WellKnownSidType.NetworkServiceSid); NativeMethods.SECURITY_ATTRIBUTES threadAttr = CreateSecurityAttributes(winIdentity == null ? WellKnownSidType.AuthenticatedUserSid : WellKnownSidType.NetworkServiceSid); lock (_createProcessLock) { NativeMethods.PROCESS_INFORMATION pi; NativeMethods.ErrorModes oldErrorMode = NativeMethods.SetErrorMode(NativeMethods.ErrorModes.SEM_FAILCRITICALERRORS); try { if (winIdentity == null) { if (!NativeMethods.CreateProcess(applicationName, commandLine, ref processAttr, ref threadAttr, true, (uint)(NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW), environment.NativeEnvironmentBlock, workingDirectory, ref si, out pi)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { if (!NativeMethods.CreateProcessAsUser( winIdentity.Token, applicationName, commandLine, ref processAttr, ref threadAttr, true, (uint)(NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW), environment.NativeEnvironmentBlock, workingDirectory, ref si, out pi)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } stdin = new FileStream(new SafeFileHandle(stdinWrite, true), FileAccess.Write, 0x1000, false); stdout = new FileStream(new SafeFileHandle(stdoutRead, true), FileAccess.Read, 0x1000, false); stderror = new FileStream(new SafeFileHandle(stderrorRead, true), FileAccess.Read, 0x1000, false); } finally { NativeMethods.SetErrorMode(oldErrorMode); if (processAttr.lpSecurityDescriptor != IntPtr.Zero) { Marshal.FreeHGlobal(processAttr.lpSecurityDescriptor); } if (threadAttr.lpSecurityDescriptor != IntPtr.Zero) { Marshal.FreeHGlobal(threadAttr.lpSecurityDescriptor); } } return(new Win32Process(pi)); } }
private static void StartProcessWithLogonNetOnly(ProcessStartInfo startInfo, bool waitForExit) { if (startInfo.UseShellExecute) { throw new InvalidOperationException("UseShellExecute must be false."); } if (startInfo.LoadUserProfile) { throw new InvalidOperationException("LoadUserProfile cannot be used."); } if (string.IsNullOrEmpty(startInfo.UserName)) { throw new InvalidOperationException("UserName is empty."); } var cmdLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments); var lpStartupInfo = new NativeMethods.STARTUPINFO(); var lpProcessInformation = new NativeMethods.PROCESS_INFORMATION(); int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= 0x8000000; } IntPtr zero = IntPtr.Zero; string workingDirectory = startInfo.WorkingDirectory; if (string.IsNullOrEmpty(workingDirectory)) { workingDirectory = Environment.CurrentDirectory; } NativeMethods.LogonFlags logonFlags = NativeMethods.LogonFlags.LOGON_NETCREDENTIALS_ONLY; //NetOnly; IntPtr passwordPrt = IntPtr.Zero; try { if (startInfo.Password == null) { passwordPrt = Marshal.StringToCoTaskMemUni(string.Empty); } else { passwordPrt = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); } int error = 0; bool flag = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, passwordPrt, logonFlags, null, cmdLine, creationFlags, zero, workingDirectory, lpStartupInfo, lpProcessInformation); if (!flag) { error = Marshal.GetLastWin32Error(); } if (!flag) { if (error != 0xc1 && error != 0xd8) { throw new Win32Exception(error); } throw new Win32Exception(error, "Invalid Application"); } } finally { if (passwordPrt != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPrt); } } if (waitForExit) { NativeMethods.WaitForSingleObject(lpProcessInformation.hProcess, 0xFFFFFFFF); } }
public Tuple <bool, int> CreateProcessAsUser(IntPtr hUserToken, string appFileName, string appArgs) { try { // Identify user from access token. WindowsIdentity userId = new WindowsIdentity(hUserToken); _logger.Log("Create process for: " + userId.Name + " [" + appFileName + " " + appArgs + "]."); userId.Dispose(); // Obtain duplicated user token (elevated if UAC is turned on/enabled). IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken); // Initialize process info and startup info. NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); IntPtr hEnvironment = IntPtr.Zero; if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true)) { _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN); } if (!NativeMethods.CreateProcessAsUser( hDuplicateToken, null, appFileName + " " + appArgs, ref lpProcessAttributes, ref lpThreadAttributes, false, (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS | (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT | (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE, hEnvironment, Path.GetDirectoryName(appFileName), ref si, out pi)) { _logger.Log("Unable to create user process [CreateProcessAsUser="******"].", Logger.MsgType.ERROR); Marshal.FreeHGlobal(hDuplicateToken); Marshal.FreeHGlobal(hEnvironment); Marshal.FreeHGlobal(hUserToken); return(new Tuple <bool, int>(false, -1)); } else { _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs); var newProcess = Process.GetProcessById(pi.dwProcessId); try { // For UI apps, wait for idle state, before continuing. newProcess.WaitForInputIdle(2000); } catch (InvalidOperationException) { // Must be a non-UI app, just give it a sec to start. Thread.Sleep(1000); } newProcess.Dispose(); Marshal.FreeHGlobal(hDuplicateToken); Marshal.FreeHGlobal(hEnvironment); Marshal.FreeHGlobal(hUserToken); return(new Tuple <bool, int>(true, pi.dwProcessId)); } } catch (Exception e) { _logger.Log(e, "Failed to create process as user."); return(new Tuple <bool, int>(false, -1)); } }
public bool CreateProcessAsUser(WindowsIdentity userId, string appFileName, string appArgs) { try { _logger.Log("Create process for: " + userId.Name); List <Tuple <uint, string> > userSessions = new WindowsHelper(_logger).GetUserSessions(); int sessionId = -1; foreach (Tuple <uint, string> logonSession in userSessions) { if (logonSession.Item2.ToLower().Equals(userId.Name.ToLower())) { sessionId = (int)logonSession.Item1; break; } } if (sessionId == -1) { _logger.Log("Failed to match any/existing logon session with user [" + userId.Name + "].", Logger.MsgType.ERROR); return(false); } if (!NativeMethods.WTSQueryUserToken((uint)sessionId, out IntPtr hUserToken)) { _logger.Log("Failed to query user token [WTSQueryUserToken=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.ERROR); return(false); } // Obtain duplicated user token (elevated if UAC is turned on/enabled). IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken, (uint)sessionId); Marshal.FreeHGlobal(hUserToken); // Initialize process info and startup info. NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); IntPtr hEnvironment = IntPtr.Zero; if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true)) { _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN); } if (!NativeMethods.CreateProcessAsUser( hDuplicateToken, null, appFileName + " " + appArgs, ref lpProcessAttributes, ref lpThreadAttributes, false, (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS | (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT | (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE, hEnvironment, Path.GetDirectoryName(appFileName), ref si, out pi)) { _logger.Log("ERROR: Unable to create user process [CreateProcessAsUser="******"]."); return(false); } else { _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs); var newProcess = Process.GetProcessById(pi.dwProcessId); try { // For UI apps, wait for idle state, before continuing. newProcess.WaitForInputIdle(2000); } catch (InvalidOperationException) { // Must be a non-UI app, just give it a sec to start. Thread.Sleep(1000); } return(true); } } catch (Exception e) { _logger.Log(e, "Failed to create process as user."); return(false); } }
/// <summary> /// If HpcServiceHost is launched to run a pre/post task, launch the pre/post task /// </summary> private static bool RunPrePostTask(ref uint exitCode) { bool prePostTaskExists = false; string prePostTaskCommandLine = Environment.GetEnvironmentVariable(Constant.PrePostTaskCommandLineEnvVar); // Check if pre/post task exists prePostTaskExists = !string.IsNullOrEmpty(prePostTaskCommandLine); // if so run it if (prePostTaskExists) { string serviceWorkingDirectory = null; // Working directory is the service assembly's directory. If we are on Azure, change to the service package's dir. If // not on azure use service assemblies directory from service config which is passed to svchost via env var so we dont // need to read the svc config file again on every CN (which is slow) if (SoaHelper.IsOnAzure()) { serviceWorkingDirectory = Utility.GetServiceLocalCacheFullPath(); } else { serviceWorkingDirectory = Environment.ExpandEnvironmentVariables( Environment.GetEnvironmentVariable(Constant.PrePostTaskOnPremiseWorkingDirEnvVar)); } NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO(); startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION(); StringBuilder commandLine = new StringBuilder(); // Run command from comspec (like node manager babysitter) to ensure env vars are expanded and command runs as if launched from node manager commandLine.AppendFormat("\"{0}\" /S /c \"{1}\"", Environment.GetEnvironmentVariable("ComSpec"), prePostTaskCommandLine); TraceHelper.TraceInfo( jobId, "Executing '{0}'", prePostTaskCommandLine); // Start the task bool ret = NativeMethods.CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, NativeMethods.CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, serviceWorkingDirectory, ref startupInfo, out processInfo); // If CreateProcess succeeded if (ret) { using (SafeWaitHandle processHandle = new SafeWaitHandle(processInfo.hProcess, true)) using (SafeWaitHandle threadHandle = new SafeWaitHandle(processInfo.hThread, true)) { if (processHandle.IsClosed || processHandle.IsInvalid) { TraceHelper.TraceError( jobId, "Process handle is invalid or closed. Task commandline = {0}", commandLine); exitCode = 1; return(true); } // Wait for task to complete NativeMethods.WaitForSingleObject(processInfo.hProcess, Timeout.Infinite); // Trace the results NativeMethods.GetExitCodeProcess(new SafeProcessHandle(processInfo.hProcess, false), out exitCode); TraceHelper.TraceInfo( jobId, "ExitCode = {0}", exitCode); } } else { int errorCode = Marshal.GetLastWin32Error(); TraceHelper.TraceError( jobId, "Cannot start pre/post task: '{0}'. Exit code = {1}", prePostTaskCommandLine, errorCode); exitCode = (uint)errorCode; } } return(prePostTaskExists); }
private bool StartWithCreateProcess(ProcessStartInfo startInfo) { if (startInfo.RedirectStandardInput) { throw new InvalidOperationException("Standard input redirect not allowed"); } if (startInfo.RedirectStandardOutput) { throw new InvalidOperationException("Standard output redirect not allowed"); } if (startInfo.RedirectStandardError) { throw new InvalidOperationException("Standard error redirect not allowed"); } //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed. if (this._Disposed) { throw new ObjectDisposedException(GetType().Name); } StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments); NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO(); NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION(); bool retVal; int errorCode = 0; // set up the creation flags paramater int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= (int)NativeMethods.CreateProcessFlags.CREATE_NO_WINDOW; startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE; } else { creationFlags |= (int)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE; switch (startInfo.WindowStyle) { case ProcessWindowStyle.Maximized: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_MAXIMIZE; break; case ProcessWindowStyle.Minimized: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_MINIMIZE; break; case ProcessWindowStyle.Hidden: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE; break; } } string workingDirectory = startInfo.WorkingDirectory; if (workingDirectory == string.Empty) { workingDirectory = ProcessUtils.StartupPath; } RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { retVal = NativeMethods.CreateProcess( null, // we don't need this since all the info is in commandLine commandLine.ToString(), // pointer to the command line string IntPtr.Zero, // pointer to process security attributes, we don't need to inheriat the handle IntPtr.Zero, // pointer to thread security attributes true, // handle inheritance flag creationFlags, // creation flags IntPtr.Zero, // pointer to new environment block workingDirectory, // pointer to current directory name ref startupInfo, // pointer to STARTUPINFO out processInfo // pointer to PROCESS_INFORMATION ); if (!retVal) { errorCode = Marshal.GetLastWin32Error(); } } if (!retVal) { if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT) { throw new Win32Exception(errorCode, "Invalid application"); } throw new Win32Exception(errorCode); } bool ret = false; if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { _ProcessHandle = processInfo.hProcess; _HaveProcessHandle = true; if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { NativeMethods.CloseHandle(processInfo.hThread); } ret = true; } return(ret); }