Exemplo n.º 1
0
        public static InputWriterOnlyPseudoConsole Create()
        {
            var(inputReader, inputWriter) = FilePal.CreatePipePair();
            var outputWriter = FilePal.OpenNullDevice(FileAccess.Write);
            var hPC          = SafePseudoConsoleHandle.Create(inputReader, outputWriter);

            return(new InputWriterOnlyPseudoConsole(hPC, inputWriter));
        }
        private SafeFileHandle OpenNullDevice(FileAccess access)
        {
            EnsureObjectsToDispose();

            var handle = FilePal.OpenNullDevice(access);

            _objectsToDispose.Add(handle);
            return(handle);
        }
        private SafeFileHandle ChooseOutput(
            OutputRedirection redirection,
            string fileName,
            SafeFileHandle handle,
            SafeFileHandle outputPipe,
            SafeFileHandle errorPipe)
        {
            switch (redirection)
            {
            case OutputRedirection.ParentOutput:
                return(ConsolePal.GetStdOutputHandleForChild() ?? OpenNullDevice(FileAccess.Write));

            case OutputRedirection.ParentError:
                return(ConsolePal.GetStdErrorHandleForChild() ?? OpenNullDevice(FileAccess.Write));

            case OutputRedirection.OutputPipe:
                return(outputPipe);

            case OutputRedirection.ErrorPipe:
                return(errorPipe);

            case OutputRedirection.File:
                return(OpenFile(fileName, FileMode.Create, FileAccess.Write, FileShare.Read));

            case OutputRedirection.AppendToFile:
                return(OpenFile(fileName, FileMode.Append, FileAccess.Write, FileShare.Read));

            case OutputRedirection.Handle:
                return(handle);

            case OutputRedirection.NullDevice:
                return(FilePal.OpenNullDevice(FileAccess.Write));

            default:
                throw new ArgumentOutOfRangeException(nameof(redirection), "Not a valid value for " + nameof(OutputRedirection) + ".");
            }
        }
Exemplo n.º 4
0
 public SafeFileHandle GetStdErrorHandleForChild(bool createNewConsole) =>
 DuplicateStdFileForChild(StdErrFileNo, createNewConsole) ?? FilePal.OpenNullDevice(System.IO.FileAccess.Write);
Exemplo n.º 5
0
 public SafeFileHandle GetStdInputHandleForChild(bool createNewConsole) =>
 DuplicateStdFileForChild(StdInFileNo, createNewConsole) ?? FilePal.OpenNullDevice(System.IO.FileAccess.Read);
Exemplo n.º 6
0
 public SafeFileHandle GetStdErrorHandleForChild(bool createNewConsole) =>
 GetStdHandleForChild(Kernel32.STD_ERROR_HANDLE, createNewConsole) ?? FilePal.OpenNullDevice(System.IO.FileAccess.Write);
Exemplo n.º 7
0
 public SafeFileHandle GetStdInputHandleForChild(bool createNewConsole) =>
 GetStdHandleForChild(Kernel32.STD_INPUT_HANDLE, createNewConsole) ?? FilePal.OpenNullDevice(System.IO.FileAccess.Read);
Exemplo n.º 8
0
        public PipelineStdHandleCreator(ref ChildProcessStartInfoInternal startInfo)
        {
            var stdInputRedirection  = startInfo.StdInputRedirection;
            var stdOutputRedirection = startInfo.StdOutputRedirection;
            var stdErrorRedirection  = startInfo.StdErrorRedirection;
            var stdInputFile         = startInfo.StdInputFile;
            var stdOutputFile        = startInfo.StdOutputFile;
            var stdErrorFile         = startInfo.StdErrorFile;
            var stdInputHandle       = startInfo.StdInputHandle;
            var stdOutputHandle      = startInfo.StdOutputHandle;
            var stdErrorHandle       = startInfo.StdErrorHandle;

            if (stdInputRedirection == InputRedirection.Handle && stdInputHandle == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdInputHandle)} must not be null.", nameof(startInfo));
            }
            if (stdInputRedirection == InputRedirection.File && stdInputFile == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdInputFile)} must not be null.", nameof(startInfo));
            }
            if (stdOutputRedirection == OutputRedirection.Handle && stdOutputHandle == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdOutputHandle)} must not be null.", nameof(startInfo));
            }
            if (IsFileRedirection(stdOutputRedirection) && stdOutputFile == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdOutputFile)} must not be null.", nameof(startInfo));
            }
            if (stdErrorRedirection == OutputRedirection.Handle && stdErrorHandle == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdErrorHandle)} must not be null.", nameof(startInfo));
            }
            if (IsFileRedirection(stdErrorRedirection) && stdErrorFile == null)
            {
                throw new ArgumentException($"{nameof(ChildProcessStartInfo.StdErrorFile)} must not be null.", nameof(startInfo));
            }

            bool redirectingToSameFile = IsFileRedirection(stdOutputRedirection) && IsFileRedirection(stdErrorRedirection) && stdOutputFile == stdErrorFile;

            if (redirectingToSameFile && stdErrorRedirection != stdOutputRedirection)
            {
                throw new ArgumentException(
                          "StdOutputRedirection and StdErrorRedirection must be the same value when both stdout and stderr redirect to the same file.",
                          nameof(startInfo));
            }

            try
            {
                if (stdInputRedirection == InputRedirection.InputPipe)
                {
                    (InputStream, _inputReadPipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.Out);
                }

                if (stdOutputRedirection == OutputRedirection.OutputPipe ||
                    stdErrorRedirection == OutputRedirection.OutputPipe)
                {
                    (OutputStream, _outputWritePipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.In);
                }

                if (stdOutputRedirection == OutputRedirection.ErrorPipe ||
                    stdErrorRedirection == OutputRedirection.ErrorPipe)
                {
                    (ErrorStream, _errorWritePipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.In);
                }

                PipelineStdIn = ChooseInput(
                    stdInputRedirection,
                    stdInputFile,
                    stdInputHandle,
                    _inputReadPipe,
                    startInfo.CreateNewConsole);

                PipelineStdOut = ChooseOutput(
                    stdOutputRedirection,
                    stdOutputFile,
                    stdOutputHandle,
                    _outputWritePipe,
                    _errorWritePipe,
                    startInfo.CreateNewConsole);

                if (redirectingToSameFile)
                {
                    PipelineStdErr = PipelineStdOut;
                }
                else
                {
                    PipelineStdErr = ChooseOutput(
                        stdErrorRedirection,
                        stdErrorFile,
                        stdErrorHandle,
                        _outputWritePipe,
                        _errorWritePipe,
                        startInfo.CreateNewConsole);
                }
            }
            catch
            {
                Dispose();
                throw;
            }
        }
        public PipelineStdHandleCreator(
            InputRedirection stdInputRedirection,
            OutputRedirection stdOutputRedirection,
            OutputRedirection stdErrorRedirection,
            string stdInputFile,
            string stdOutputFile,
            string stdErrorFile,
            SafeFileHandle stdInputHandle,
            SafeFileHandle stdOutputHandle,
            SafeFileHandle stdErrorHandle)
        {
            if (stdInputRedirection == InputRedirection.Handle && stdInputHandle == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdInputHandle));
            }
            if (stdInputRedirection == InputRedirection.File && stdInputFile == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdInputFile));
            }
            if (stdOutputRedirection == OutputRedirection.Handle && stdOutputHandle == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdOutputHandle));
            }
            if (IsFileRedirection(stdOutputRedirection) && stdOutputFile == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdOutputFile));
            }
            if (stdErrorRedirection == OutputRedirection.Handle && stdErrorHandle == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdErrorHandle));
            }
            if (IsFileRedirection(stdErrorRedirection) && stdErrorFile == null)
            {
                throw new ArgumentNullException(nameof(ChildProcessStartInfo.StdErrorFile));
            }

            bool redirectingToSameFile = IsFileRedirection(stdOutputRedirection) && IsFileRedirection(stdErrorRedirection) && stdOutputFile == stdErrorFile;

            if (redirectingToSameFile && stdErrorRedirection != stdOutputRedirection)
            {
                throw new ArgumentException(
                          "StdOutputRedirection and StdErrorRedirection must be the same value when both stdout and stderr redirect to the same file.",
                          nameof(ChildProcessStartInfo.StdErrorRedirection));
            }

            try
            {
                if (stdInputRedirection == InputRedirection.InputPipe)
                {
                    (this.InputStream, _inputReadPipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.Out);
                }

                if (stdOutputRedirection == OutputRedirection.OutputPipe ||
                    stdErrorRedirection == OutputRedirection.OutputPipe)
                {
                    (this.OutputStream, _outputWritePipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.In);
                }

                if (stdOutputRedirection == OutputRedirection.ErrorPipe ||
                    stdErrorRedirection == OutputRedirection.ErrorPipe)
                {
                    (this.ErrorStream, _errorWritePipe) = FilePal.CreatePipePairWithAsyncServerSide(System.IO.Pipes.PipeDirection.In);
                }

                this.PipelineStdIn = ChooseInput(
                    stdInputRedirection,
                    stdInputFile,
                    stdInputHandle,
                    _inputReadPipe);

                this.PipelineStdOut = ChooseOutput(
                    stdOutputRedirection,
                    stdOutputFile,
                    stdOutputHandle,
                    _outputWritePipe,
                    _errorWritePipe);

                if (redirectingToSameFile)
                {
                    this.PipelineStdErr = this.PipelineStdOut;
                }
                else
                {
                    this.PipelineStdErr = ChooseOutput(
                        stdErrorRedirection,
                        stdErrorFile,
                        stdErrorHandle,
                        _outputWritePipe,
                        _errorWritePipe);
                }
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemplo n.º 10
0
        // Change the code page of the specified pseudo console by invoking chcp.com on it.
        private static unsafe void ChangeCodePage(
            InputWriterOnlyPseudoConsole pseudoConsole,
            int codePage,
            string?workingDirectory)
        {
            var commandLine = new StringBuilder(ChcpPath.Length + 5);

            WindowsCommandLineUtil.AppendStringQuoted(commandLine, ChcpPath);
            commandLine.Append(' ');
            commandLine.Append(codePage.ToString(CultureInfo.InvariantCulture));

            using var inheritableHandleStore = new InheritableHandleStore(3);
            using var nullDevice             = FilePal.OpenNullDevice(FileAccess.ReadWrite);
            var childStdIn  = inheritableHandleStore.Add(nullDevice);
            var childStdOut = inheritableHandleStore.Add(nullDevice);
            var childStdErr = inheritableHandleStore.Add(nullDevice);

            SafeProcessHandle?processHandle = null;

            try
            {
                Span <IntPtr> inheritableHandles = stackalloc IntPtr[inheritableHandleStore.Count];
                inheritableHandleStore.DangerousGetHandles(inheritableHandles);
                fixed(IntPtr *pInheritableHandles = inheritableHandles)
                {
                    using var attr = new ProcThreadAttributeList(2);
                    attr.UpdatePseudoConsole(pseudoConsole.Handle.DangerousGetHandle());
                    attr.UpdateHandleList(pInheritableHandles, inheritableHandles.Length);

                    const int CreationFlags =
                        Kernel32.CREATE_UNICODE_ENVIRONMENT
                        | Kernel32.EXTENDED_STARTUPINFO_PRESENT;

                    SafeThreadHandle threadHandle;

                    (_, processHandle, threadHandle) = InvokeCreateProcess(
                        commandLine,
                        CreationFlags,
                        null,
                        workingDirectory,
                        childStdIn,
                        childStdOut,
                        childStdErr,
                        attr);
                    threadHandle.Dispose();
                }

                using var waitHandle = new WindowsProcessWaitHandle(processHandle);
                waitHandle.WaitOne();

                if (!Kernel32.GetExitCodeProcess(processHandle, out var exitCode))
                {
                    throw new Win32Exception();
                }

                if (exitCode != 0)
                {
                    ThrowHelper.ThrowChcpFailedException(codePage, exitCode, nameof(codePage));
                }
            }
            finally
            {
                processHandle?.Dispose();
            }
        }