public static string ExecuteForStandardOutput(ChildProcessStartInfo si, Encoding?encoding = null) { using var p = ChildProcess.Start(si); if (p.HasStandardInput) { p.StandardInput.Close(); } if (p.HasStandardError) { p.StandardError.Close(); } using var sr = new StreamReader(p.StandardOutput, encoding ?? Encoding.UTF8); var standardOutput = sr.ReadToEnd(); p.WaitForExit(); if (p.ExitCode != 0) { throw new ChildProcessFailedException($"Child process failed with exit code {p.ExitCode} (0x{p.ExitCode:X8})."); } return(standardOutput); }
public void ConnectsInputPipe() { using var tmp = new TemporaryDirectory(); var outFile = Path.Combine(tmp.Location, "out"); var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoBack") { StdInputRedirection = InputRedirection.InputPipe, StdOutputRedirection = OutputRedirection.File, StdOutputFile = outFile, StdErrorRedirection = OutputRedirection.NullDevice, }; using var sut = ChildProcess.Start(si); const string Text = "foo"; using (var sw = new StreamWriter(sut.StandardInput)) { sw.Write(Text); } sut.WaitForExit(); Assert.True(sut.HasStandardInput); Assert.False(sut.HasStandardOutput); Assert.False(sut.HasStandardError); Assert.Equal(Text, File.ReadAllText(outFile)); }
public void RedirectionToNull() { { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoBack") { StdInputRedirection = InputRedirection.NullDevice, StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.NullDevice, }; using var sut = ChildProcess.Start(si); sut.WaitForExit(); Assert.Equal(0, sut.ExitCode); } { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoOutAndError") { StdInputRedirection = InputRedirection.NullDevice, StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.NullDevice, }; using var sut = ChildProcess.Start(si); sut.WaitForExit(); Assert.Equal(0, sut.ExitCode); } }
public void CanObtainExitCode() { { var si = new ChildProcessStartInfo( TestUtil.DotnetCommandName, TestUtil.TestChildPath, "ExitCode", "0"); using var sut = ChildProcess.Start(si); sut.WaitForExit(); Assert.Equal(0, sut.ExitCode); } { // An exit code is 32-bit on Windows while it is 8-bit on POSIX. int nonZeroExitCode = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? unchecked ((int)0xc0000005) : 255; var si = new ChildProcessStartInfo( TestUtil.DotnetCommandName, TestUtil.TestChildPath, "ExitCode", nonZeroExitCode.ToString(CultureInfo.InvariantCulture)); using var sut = ChildProcess.Start(si); sut.WaitForExit(); Assert.NotEqual(0, sut.ExitCode); Assert.Equal(nonZeroExitCode, sut.ExitCode); } }
public void CanSendSignal() { var si = new ChildProcessStartInfo(TestUtil.TestChildNativePath, "ReportSignal") { StdInputRedirection = InputRedirection.InputPipe, StdOutputRedirection = OutputRedirection.OutputPipe, }; using var sut = ChildProcess.Start(si); Assert.True(sut.CanSignal); Assert.Equal('R', sut.StandardOutput.ReadByte()); sut.SignalInterrupt(); Assert.Equal('I', sut.StandardOutput.ReadByte()); sut.SignalInterrupt(); Assert.Equal('I', sut.StandardOutput.ReadByte()); if (!HasWorkaroundForWindows1809) { // NOTE: On Windows, a console app cannot cancel CTRL_CLOSE_EVENT (generated when the attached pseudo console is closed). // It will be killed after the 5s-timeout elapses. Once we call SignalTermination, we must treat the app as already terminated. // https://docs.microsoft.com/en-us/windows/console/handlerroutine#timeouts sut.SignalTermination(); Assert.Equal('T', sut.StandardOutput.ReadByte()); } sut.Kill(); sut.WaitForExit(); Assert.NotEqual(0, sut.ExitCode); }
private static ChildProcessImpl CreateForWaitForExitTest() { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoBack") { StdInputRedirection = InputRedirection.InputPipe, StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.NullDevice, }; return((ChildProcessImpl)ChildProcess.Start(si)); }
public void ChildProcessWaitForAsyncIsTrulyAsynchronous() { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "Sleep", "1000") { StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.NullDevice, }; using var sut = ChildProcess.Start(si); WaitForAsyncIsTrulyAsynchronous(sut); sut.WaitForExit(); Assert.Equal(0, sut.ExitCode); }
public void ExitCodeThrowsBeforeChildExits() { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoBack") { StdInputRedirection = InputRedirection.InputPipe, }; using var sut = ChildProcess.Start(si); Assert.Throws <InvalidOperationException>(() => sut.ExitCode); sut.StandardInput.Close(); sut.WaitForExit(); Assert.Equal(0, sut.ExitCode); }
public void StreamPropertiesThrowWhenNoPipeAssociated() { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "ExitCode", "0") { StdInputRedirection = InputRedirection.NullDevice, StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.NullDevice, }; using var sut = ChildProcess.Start(si); Assert.False(sut.HasStandardInput); Assert.False(sut.HasStandardOutput); Assert.False(sut.HasStandardError); Assert.Throws <InvalidOperationException>(() => sut.StandardInput); Assert.Throws <InvalidOperationException>(() => sut.StandardOutput); Assert.Throws <InvalidOperationException>(() => sut.StandardError); sut.WaitForExit(); }
public void ConnectsErrorPipe() { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoOutAndError") { StdInputRedirection = InputRedirection.NullDevice, StdOutputRedirection = OutputRedirection.NullDevice, StdErrorRedirection = OutputRedirection.ErrorPipe, }; using var sut = ChildProcess.Start(si); using var sr = new StreamReader(sut.StandardError); var output = sr.ReadToEnd(); sut.WaitForExit(); Assert.False(sut.HasStandardInput); Assert.False(sut.HasStandardOutput); Assert.True(sut.HasStandardError); Assert.Equal(0, sut.ExitCode); Assert.Equal("TestChild.Error", output); }
public void CannotSendSignalIfAttachedToCurrentConsole() { var si = new ChildProcessStartInfo(TestUtil.TestChildNativePath, "ReportSignal") { StdInputRedirection = InputRedirection.InputPipe, StdOutputRedirection = OutputRedirection.OutputPipe, Flags = ChildProcessFlags.AttachToCurrentConsole, }; using var sut = ChildProcess.Start(si); Assert.False(sut.CanSignal); Assert.Throws<InvalidOperationException>(() => sut.SignalInterrupt()); Assert.Throws<InvalidOperationException>(() => sut.SignalTermination()); Assert.Equal('R', sut.StandardOutput.ReadByte()); sut.Kill(); sut.WaitForExit(); Assert.NotEqual(0, sut.ExitCode); }
public async Task ConnectOutputAndErrorPipes() { { var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoOutAndError") { StdOutputRedirection = OutputRedirection.OutputPipe, StdErrorRedirection = OutputRedirection.ErrorPipe, }; using var sut = ChildProcess.Start(si); await Impl(sut, "TestChild.Out", "TestChild.Error"); } { // invert stdout and stderr var si = new ChildProcessStartInfo(TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoOutAndError") { StdOutputRedirection = OutputRedirection.ErrorPipe, StdErrorRedirection = OutputRedirection.OutputPipe, }; using var sut = ChildProcess.Start(si); await Impl(sut, "TestChild.Error", "TestChild.Out"); }
private static IChildProcess CreateProcessTree(AnonymousPipeServerStream stdOutputPipe) { var si = new ChildProcessStartInfo( TestUtil.DotnetCommandName, TestUtil.TestChildPath, "SpawnAndWait", TestUtil.DotnetCommandName, TestUtil.TestChildPath, "EchoAndSleepAndEcho", "S", SleepMilliseconds, "Exited") { StdInputRedirection = InputRedirection.NullDevice, StdOutputRedirection = OutputRedirection.Handle, StdOutputHandle = stdOutputPipe.ClientSafePipeHandle, StdErrorRedirection = OutputRedirection.NullDevice, }; var p = ChildProcess.Start(si); try { stdOutputPipe.DisposeLocalCopyOfClientHandle(); // Wait for the grand child to echo. Assert.Equal((byte)'S', stdOutputPipe.ReadByte()); } catch { p.Dispose(); throw; } return(p); }
public void RejectsInvalidRedirection() { using var tmp = new TemporaryDirectory(); var filePath = Path.Combine(tmp.Location, "file"); // null Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdInputRedirection = InputRedirection.Handle })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdInputRedirection = InputRedirection.File })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputRedirection = OutputRedirection.Handle })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputRedirection = OutputRedirection.File })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputRedirection = OutputRedirection.AppendToFile })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdErrorRedirection = OutputRedirection.Handle })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdErrorRedirection = OutputRedirection.File })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdErrorRedirection = OutputRedirection.AppendToFile })); // Enum value out of range Assert.Throws <ArgumentOutOfRangeException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdInputRedirection = (InputRedirection)(-1) })); Assert.Throws <ArgumentOutOfRangeException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputRedirection = (OutputRedirection)(-1) })); Assert.Throws <ArgumentOutOfRangeException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdErrorRedirection = (OutputRedirection)(-1) })); // When both stdout and stderr are redirected to the same file, they must have the same "append" option. Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputFile = filePath, StdOutputRedirection = OutputRedirection.File, StdErrorFile = filePath, StdErrorRedirection = OutputRedirection.AppendToFile, })); Assert.Throws <ArgumentException>(() => ChildProcess.Start( new ChildProcessStartInfo(TestUtil.TestChildNativePath) { StdOutputFile = filePath, StdOutputRedirection = OutputRedirection.AppendToFile, StdErrorFile = filePath, StdErrorRedirection = OutputRedirection.File, })); }