/// <summary> /// Creates a process based on the CreateProcess API call. /// </summary> /// <param name="lpApplicationName">The name of the executable or batch file to execute</param> /// <param name="lpCommandLine">The command line to execute, typically this includes lpApplication as the first argument</param> /// <param name="lpCurrentDirectory">The full path to the current directory for the process, null will have the same cwd as the calling process</param> /// <param name="environment">A dictionary of key/value pairs to define the new process environment</param> /// <param name="stdin">A byte array to send over the stdin pipe</param> /// <returns>Result object that contains the command output and return code</returns> public static Result CreateProcess(string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, IDictionary environment, byte[] stdin) { NativeHelpers.ProcessCreationFlags creationFlags = NativeHelpers.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT | NativeHelpers.ProcessCreationFlags.EXTENDED_STARTUPINFO_PRESENT; NativeHelpers.PROCESS_INFORMATION pi = new NativeHelpers.PROCESS_INFORMATION(); NativeHelpers.STARTUPINFOEX si = new NativeHelpers.STARTUPINFOEX(); si.startupInfo.dwFlags = NativeHelpers.StartupInfoFlags.USESTDHANDLES; SafeFileHandle stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinRead, stdinWrite; CreateStdioPipes(si, out stdoutRead, out stdoutWrite, out stderrRead, out stderrWrite, out stdinRead, out stdinWrite); FileStream stdinStream = new FileStream(stdinWrite, FileAccess.Write); // $null from PowerShell ends up as an empty string, we need to convert back as an empty string doesn't // make sense for these parameters if (lpApplicationName == "") { lpApplicationName = null; } if (lpCurrentDirectory == "") { lpCurrentDirectory = null; } using (SafeMemoryBuffer lpEnvironment = CreateEnvironmentPointer(environment)) { // Create console with utf-8 CP if no existing console is present bool isConsole = false; if (NativeMethods.GetConsoleWindow() == IntPtr.Zero) { isConsole = NativeMethods.AllocConsole(); // Set console input/output codepage to UTF-8 NativeMethods.SetConsoleCP(65001); NativeMethods.SetConsoleOutputCP(65001); } try { StringBuilder commandLine = new StringBuilder(lpCommandLine); if (!NativeMethods.CreateProcessW(lpApplicationName, commandLine, IntPtr.Zero, IntPtr.Zero, true, creationFlags, lpEnvironment, lpCurrentDirectory, si, out pi)) { throw new Win32Exception("CreateProcessW() failed"); } } finally { if (isConsole) { NativeMethods.FreeConsole(); } } } return(WaitProcess(stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinStream, stdin, pi.hProcess)); }
public static extern bool CreateProcessW( [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName, StringBuilder lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, NativeHelpers.ProcessCreationFlags dwCreationFlags, SafeMemoryBuffer lpEnvironment, [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory, NativeHelpers.STARTUPINFOEX lpStartupInfo, out NativeHelpers.PROCESS_INFORMATION lpProcessInformation);