/// <summary> /// Creates a new process under this debugging pipeline. /// </summary> /// <param name="application">raw application to launch. Passed directly to kernel32!CreateProcess.</param> /// <param name="commandArgs">raw arguments to pass to the debuggee. Passed directly to kernel32!CreateProcess.</param> /// <param name="newConsole">true if the debuggee should get a new console, else false</param> /// <param name="debugChild">true if this should debug child processes, else false to debug just the /// launched processes.</param> /// <returns>NativeDbgProcess instance for newly created process</returns> /// <seealso cref="Attach"/> /// <remarks>Pump the process for debug events by calling WaitForDebugEvent. /// Create a process under the debugger. /// This passes application and commandArgs directly to Passed directly to kernel32!CreateProcess and /// does not do any filtering on them.</remarks> public NativeDbgProcess CreateProcessDebugRaw(string application, string commandArgs, bool newConsole, bool debugChild) { // This is a pretty rich overload. We should considering just using a rich structure (like // ProcessStartInfo) instead of ever growign signatures. ProcessStartInfo isn't perfect: // - it's missing some flags like child-process debugging. // - it has extra flags like UseShellExecute. NativeMethods.CreateProcessFlags flags = NativeMethods.CreateProcessFlags.DEBUG_PROCESS; if (!debugChild) { flags |= NativeMethods.CreateProcessFlags.DEBUG_ONLY_THIS_PROCESS; } if (newConsole) { flags |= NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE; } return(CreateProcessDebugRawWorker(application, commandArgs, flags)); }
private NativeDbgProcess CreateProcessDebugWorker(string application, string commandArgs, NativeMethods.CreateProcessFlags flags) { if (application == null) { throw new ArgumentException("can't be null", "application"); } // Compensate for Win32's behavior, where arg[0] is the application name. if (commandArgs != null) { commandArgs = application + " " + commandArgs; } // This is using definition imports from Mdbg core, where these are classes. var pi = new PROCESS_INFORMATION(); // class var si = new STARTUPINFO(); // struct NativeMethods.CreateProcess( application, commandArgs, IntPtr.Zero, // process attributes IntPtr.Zero, // thread attributes false, // inherit handles, NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE | flags, IntPtr.Zero, // env block null, // current dir si, pi); // We'll close these handle now. We'll get them again from the CreateProcess debug event. NativeMethods.CloseHandle(pi.hProcess); NativeMethods.CloseHandle(pi.hThread); return(CreateNew(pi.dwProcessId)); }
static void Main(string[] args) { string desktopName = "MyDesktop"; string appPath = @"%SystemRoot%\system32\cmd.exe"; string parameters = @"/c dir C:\ >%TEMP%\dir.txt"; IntPtr hDesktop = IntPtr.Zero; NativeMethods.ProcessInformation processInfo = new NativeMethods.ProcessInformation(); bool isSuccess; try { hDesktop = NativeMethods.CreateDesktop(desktopName, null, null, 0, NativeMethods.ACCESS_MASK.MAXIMUM_ALLOWED, null); if (hDesktop == IntPtr.Zero) { DisplayLastErrorMessage(); return; } NativeMethods.StartupInfo startupInfo = new NativeMethods.StartupInfo(); NativeMethods.CreateProcessFlags dwCreationFlags = NativeMethods.CreateProcessFlags.NormalPriorityClass; startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.StartupInfo)); startupInfo.lpDesktop = "WinSta0\\" + desktopName; string currentDirectory = Environment.CurrentDirectory; appPath = Environment.ExpandEnvironmentVariables(appPath); //if (appPath.IndexOf (' ') != -1) // appPath = '\"' + appPath + '\"'; StringBuilder sbParameters = new StringBuilder(3 + appPath.Length + parameters.Length); if (appPath.IndexOf(' ') != -1) { sbParameters.Append('\"'); sbParameters.Append(appPath); sbParameters.Append('\"'); } else { sbParameters.Append(appPath); } sbParameters.Append(' '); sbParameters.Append(parameters); // appPath - full path to the exe without having " if the file has blanks in the path isSuccess = NativeMethods.CreateProcess(appPath, sbParameters.ToString(), IntPtr.Zero, IntPtr.Zero, false, dwCreationFlags, IntPtr.Zero, currentDirectory, ref startupInfo, out processInfo); if (!isSuccess) { DisplayLastErrorMessage(); return; } NativeMethods.CloseHandle(processInfo.hThread); processInfo.hThread = IntPtr.Zero; if (NativeMethods.WaitForSingleObject(processInfo.hProcess, NativeMethods.Infinite) == NativeMethods.WaitObject0) { Console.WriteLine("the process is ended"); } } finally { if (processInfo.hThread != IntPtr.Zero) { isSuccess = NativeMethods.CloseHandle(processInfo.hThread); } if (processInfo.hProcess != IntPtr.Zero) { isSuccess = NativeMethods.CloseHandle(processInfo.hProcess); } if (hDesktop != IntPtr.Zero) { isSuccess = NativeMethods.CloseDesktop(hDesktop); } } }
public bool StartAsUser(IntPtr userToken) { _processInformation = new NativeMethods.ProcessInformation(); NativeMethods.StartupInfo startupInfo = new NativeMethods.StartupInfo(); switch (StartInfo.WindowStyle) { case ProcessWindowStyle.Hidden: startupInfo.wShowWindow = SW_HIDE; break; case ProcessWindowStyle.Maximized: startupInfo.wShowWindow = SW_MAXIMIZE; break; case ProcessWindowStyle.Minimized: startupInfo.wShowWindow = SW_MINIMIZE; break; case ProcessWindowStyle.Normal: startupInfo.wShowWindow = SW_SHOW; break; } CreateStandardPipe(out _stdinReadHandle, out _stdinWriteHandle, STD_INPUT_HANDLE, true, StartInfo.RedirectStandardInput); CreateStandardPipe(out _stdoutReadHandle, out _stdoutWriteHandle, STD_OUTPUT_HANDLE, false, StartInfo.RedirectStandardOutput); CreateStandardPipe(out _stderrReadHandle, out _stderrWriteHandle, STD_ERROR_HANDLE, false, StartInfo.RedirectStandardError); startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startupInfo.hStdInput = _stdinReadHandle; startupInfo.hStdOutput = _stdoutWriteHandle; startupInfo.hStdError = _stderrWriteHandle; NativeMethods.CreateProcessFlags createFlags = NativeMethods.CreateProcessFlags.CreateNewConsole | NativeMethods.CreateProcessFlags.CreateNewProcessGroup | NativeMethods.CreateProcessFlags.CreateDefaultErrorMode; if (StartInfo.CreateNoWindow) { startupInfo.wShowWindow = SW_HIDE; createFlags |= NativeMethods.CreateProcessFlags.CreateNoWindow; } // Create process as user, fail hard if this is unsuccessful so it can be caught in EncoderUnit if (!NativeMethods.CreateProcessAsUserW(userToken, null, GetCommandLine(), IntPtr.Zero, IntPtr.Zero, true, createFlags, IntPtr.Zero, null, startupInfo, out _processInformation)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "ImpersonationProcess: CreateProcessAsUser failed"); } if (_processInformation.hThread != (IntPtr)(-1)) { ImpersonationHelper.SafeCloseHandle(ref _processInformation.hThread); _processInformation.hThread = IntPtr.Zero; } if (StartInfo.RedirectStandardInput) { ImpersonationHelper.SafeCloseHandle(ref _stdinReadHandle); StreamWriter standardInput = new StreamWriter(new FileStream(_stdinWriteHandle, FileAccess.Write, 4096), Console.Out.Encoding) { AutoFlush = true }; SetField("standardInput", standardInput); } if (StartInfo.RedirectStandardOutput) { ImpersonationHelper.SafeCloseHandle(ref _stdoutWriteHandle); StreamReader standardOutput = new StreamReader(new FileStream(_stdoutReadHandle, FileAccess.Read, 4096), StartInfo.StandardOutputEncoding); SetField("standardOutput", standardOutput); } if (StartInfo.RedirectStandardError) { ImpersonationHelper.SafeCloseHandle(ref _stderrWriteHandle); StreamReader standardError = new StreamReader(new FileStream(_stderrReadHandle, FileAccess.Read, 4096), StartInfo.StandardErrorEncoding); SetField("standardError", standardError); } // Workaround to get process handle as non-public SafeProcessHandle Assembly processAssembly = typeof(System.Diagnostics.Process).Assembly; Type processManager = processAssembly.GetType("System.Diagnostics.ProcessManager"); object safeProcessHandle = processManager.InvokeMember("OpenProcess", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, this, new object[] { _processInformation.dwProcessId, 0x100000, false }); InvokeMethod("SetProcessHandle", safeProcessHandle); InvokeMethod("SetProcessId", _processInformation.dwProcessId); return(true); }