diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FileDescriptors.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FileDescriptors.cs
deleted file mode 100644
index 614c77c5827502..00000000000000
--- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FileDescriptors.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Win32.SafeHandles;
-
-internal static partial class Interop
-{
- internal static partial class Sys
- {
- internal static class FileDescriptors
- {
- internal static readonly SafeFileHandle STDIN_FILENO = CreateFileHandle(0);
- internal static readonly SafeFileHandle STDOUT_FILENO = CreateFileHandle(1);
- internal static readonly SafeFileHandle STDERR_FILENO = CreateFileHandle(2);
-
- private static SafeFileHandle CreateFileHandle(int fileNumber)
- {
- return new SafeFileHandle((IntPtr)fileNumber, ownsHandle: false);
- }
- }
- }
-}
diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs
index da47ef8eb1b9da..beb79d77d5165b 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs
@@ -3,14 +3,13 @@
using System;
using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
internal static partial class Interop
{
internal static partial class Sys
{
- [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_IsATty", SetLastError = true)]
+ [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_IsATty")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal static partial bool IsATty(SafeFileHandle fd);
+ internal static partial bool IsATty(IntPtr fd);
}
}
diff --git a/src/libraries/System.Console/ref/System.Console.cs b/src/libraries/System.Console/ref/System.Console.cs
index 6d814278c1ae20..ed6a329434b08b 100644
--- a/src/libraries/System.Console/ref/System.Console.cs
+++ b/src/libraries/System.Console/ref/System.Console.cs
@@ -101,6 +101,10 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth
public static System.IO.Stream OpenStandardError() { throw null; }
public static System.IO.Stream OpenStandardError(int bufferSize) { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
+ public static Microsoft.Win32.SafeHandles.SafeFileHandle OpenStandardErrorHandle() { throw null; }
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
@@ -108,9 +112,18 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static System.IO.Stream OpenStandardInput(int bufferSize) { throw null; }
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
+ public static Microsoft.Win32.SafeHandles.SafeFileHandle OpenStandardInputHandle() { throw null; }
public static System.IO.Stream OpenStandardOutput() { throw null; }
public static System.IO.Stream OpenStandardOutput(int bufferSize) { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
+ public static Microsoft.Win32.SafeHandles.SafeFileHandle OpenStandardOutputHandle() { throw null; }
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static int Read() { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
diff --git a/src/libraries/System.Console/src/System.Console.csproj b/src/libraries/System.Console/src/System.Console.csproj
index 0b24fa4c0cb1ff..802f7e0432dd4c 100644
--- a/src/libraries/System.Console/src/System.Console.csproj
+++ b/src/libraries/System.Console/src/System.Console.csproj
@@ -58,17 +58,13 @@
-
-
+
-
@@ -99,8 +95,6 @@
Link="Common\Interop\Unix\Interop.Libraries.cs" />
-
@@ -227,10 +221,6 @@
Link="Common\Interop\Unix\Interop.IOErrors.cs" />
-
-
+ /// Gets the standard input handle.
+ ///
+ /// A representing the standard input handle.
+ ///
+ /// The returned handle does not own the underlying resource, so disposing it will not close the standard input handle.
+ ///
+ [UnsupportedOSPlatform("android")]
+ [UnsupportedOSPlatform("browser")]
+ [UnsupportedOSPlatform("ios")]
+ [UnsupportedOSPlatform("tvos")]
+ public static SafeFileHandle OpenStandardInputHandle()
+ {
+ return ConsolePal.OpenStandardInputHandle();
+ }
+
+ ///
+ /// Gets the standard output handle.
+ ///
+ /// A representing the standard output handle.
+ ///
+ /// The returned handle does not own the underlying resource, so disposing it will not close the standard output handle.
+ ///
+ [UnsupportedOSPlatform("android")]
+ [UnsupportedOSPlatform("ios")]
+ [UnsupportedOSPlatform("tvos")]
+ public static SafeFileHandle OpenStandardOutputHandle()
+ {
+ return ConsolePal.OpenStandardOutputHandle();
+ }
+
+ ///
+ /// Gets the standard error handle.
+ ///
+ /// A representing the standard error handle.
+ ///
+ /// The returned handle does not own the underlying resource, so disposing it will not close the standard error handle.
+ ///
+ [UnsupportedOSPlatform("android")]
+ [UnsupportedOSPlatform("ios")]
+ [UnsupportedOSPlatform("tvos")]
+ public static SafeFileHandle OpenStandardErrorHandle()
+ {
+ return ConsolePal.OpenStandardErrorHandle();
+ }
+
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Android.cs b/src/libraries/System.Console/src/System/ConsolePal.Android.cs
index 2be7b49d595e9d..58e29f3ab758bb 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Android.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Android.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
+using Microsoft.Win32.SafeHandles;
#pragma warning disable IDE0060
@@ -30,6 +31,12 @@ internal static void EnsureConsoleInitialized() { }
public static Stream OpenStandardError() => new LogcatStream(OutputEncoding);
+ public static SafeFileHandle OpenStandardInputHandle() => throw new PlatformNotSupportedException();
+
+ public static SafeFileHandle OpenStandardOutputHandle() => throw new PlatformNotSupportedException();
+
+ public static SafeFileHandle OpenStandardErrorHandle() => throw new PlatformNotSupportedException();
+
public static Encoding InputEncoding => throw new PlatformNotSupportedException();
public static void SetConsoleInputEncoding(Encoding enc) => throw new PlatformNotSupportedException();
diff --git a/src/libraries/System.Console/src/System/ConsolePal.WebAssembly.cs b/src/libraries/System.Console/src/System/ConsolePal.Browser.cs
similarity index 90%
rename from src/libraries/System.Console/src/System/ConsolePal.WebAssembly.cs
rename to src/libraries/System.Console/src/System/ConsolePal.Browser.cs
index e02991d6baf31c..40d2cd6d8bfca9 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.WebAssembly.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Browser.cs
@@ -8,11 +8,11 @@
namespace System
{
- internal sealed class WasmConsoleStream : ConsoleStream
+ internal sealed class BrowserConsoleStream : ConsoleStream
{
private readonly SafeFileHandle _handle;
- internal WasmConsoleStream(SafeFileHandle handle, FileAccess access)
+ internal BrowserConsoleStream(SafeFileHandle handle, FileAccess access)
: base(access)
{
_handle = handle;
@@ -83,14 +83,22 @@ internal static void EnsureConsoleInitialized() { }
public static Stream OpenStandardOutput()
{
- return new WasmConsoleStream(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDOUT_FILENO), FileAccess.Write);
+ return new BrowserConsoleStream(OpenStandardOutputHandle(), FileAccess.Write);
}
public static Stream OpenStandardError()
{
- return new WasmConsoleStream(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDERR_FILENO), FileAccess.Write);
+ return new BrowserConsoleStream(OpenStandardErrorHandle(), FileAccess.Write);
}
+ public static SafeFileHandle OpenStandardInputHandle() => throw new PlatformNotSupportedException();
+
+ public static SafeFileHandle OpenStandardOutputHandle() => OpenStandardHandle(1);
+
+ public static SafeFileHandle OpenStandardErrorHandle() => OpenStandardHandle(2);
+
+ private static SafeFileHandle OpenStandardHandle(IntPtr fd) => new SafeFileHandle(fd, ownsHandle: false);
+
public static Encoding InputEncoding => throw new PlatformNotSupportedException();
public static void SetConsoleInputEncoding(Encoding enc) => throw new PlatformNotSupportedException();
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
index 98aca9d7ef698b..57d4ef11fd62e3 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
@@ -45,20 +45,28 @@ internal static partial class ConsolePal
public static Stream OpenStandardInput()
{
- return new UnixConsoleStream(Interop.CheckIo(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDIN_FILENO)), FileAccess.Read,
+ return new UnixConsoleStream(OpenStandardInputHandle(), FileAccess.Read,
useReadLine: !Console.IsInputRedirected);
}
public static Stream OpenStandardOutput()
{
- return new UnixConsoleStream(Interop.CheckIo(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDOUT_FILENO)), FileAccess.Write);
+ return new UnixConsoleStream(OpenStandardOutputHandle(), FileAccess.Write);
}
public static Stream OpenStandardError()
{
- return new UnixConsoleStream(Interop.CheckIo(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDERR_FILENO)), FileAccess.Write);
+ return new UnixConsoleStream(OpenStandardErrorHandle(), FileAccess.Write);
}
+ public static SafeFileHandle OpenStandardInputHandle() => OpenStandardHandle(0);
+
+ public static SafeFileHandle OpenStandardOutputHandle() => OpenStandardHandle(1);
+
+ public static SafeFileHandle OpenStandardErrorHandle() => OpenStandardHandle(2);
+
+ private static SafeFileHandle OpenStandardHandle(IntPtr fd) => new SafeFileHandle(fd, ownsHandle: false);
+
public static Encoding InputEncoding
{
get { return GetConsoleEncoding(); }
@@ -660,7 +668,7 @@ static void TransferBytes(ReadOnlySpan src, StdInReader dst)
/// Gets whether the specified file descriptor was redirected.
/// It's considered redirected if it doesn't refer to a terminal.
///
- private static bool IsHandleRedirected(SafeFileHandle fd)
+ private static bool IsHandleRedirected(IntPtr fd)
{
return !Interop.Sys.IsATty(fd);
}
@@ -671,7 +679,7 @@ private static bool IsHandleRedirected(SafeFileHandle fd)
///
public static bool IsInputRedirectedCore()
{
- return IsHandleRedirected(Interop.Sys.FileDescriptors.STDIN_FILENO);
+ return IsHandleRedirected(0);
}
/// Gets whether Console.Out is redirected.
@@ -679,7 +687,7 @@ public static bool IsInputRedirectedCore()
///
public static bool IsOutputRedirectedCore()
{
- return IsHandleRedirected(Interop.Sys.FileDescriptors.STDOUT_FILENO);
+ return IsHandleRedirected(1);
}
/// Gets whether Console.Error is redirected.
@@ -687,7 +695,7 @@ public static bool IsOutputRedirectedCore()
///
public static bool IsErrorRedirectedCore()
{
- return IsHandleRedirected(Interop.Sys.FileDescriptors.STDERR_FILENO);
+ return IsHandleRedirected(2);
}
/// Creates an encoding from the current environment.
@@ -889,8 +897,8 @@ private static unsafe void EnsureInitializedCore()
// This also resets it for termination due to an unhandled exception.
AppDomain.CurrentDomain.UnhandledException += (_, _) => { Interop.Sys.UninitializeTerminal(); };
- s_terminalHandle = !Console.IsOutputRedirected ? Interop.Sys.FileDescriptors.STDOUT_FILENO :
- !Console.IsInputRedirected ? Interop.Sys.FileDescriptors.STDIN_FILENO :
+ s_terminalHandle = !Console.IsOutputRedirected ? OpenStandardOutputHandle() :
+ !Console.IsInputRedirected ? OpenStandardInputHandle() :
null;
// Provide the native lib with the correct code from the terminfo to transition us into
@@ -1108,7 +1116,7 @@ private static void InvalidateTerminalSettings()
// DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is set.
// In both cases, they are written to stdout.
internal static void WriteTerminalAnsiColorString(string? value)
- => WriteTerminalAnsiString(value, Interop.Sys.FileDescriptors.STDOUT_FILENO, mayChangeCursorPosition: false);
+ => WriteTerminalAnsiString(value, OpenStandardOutputHandle(), mayChangeCursorPosition: false);
/// Writes a terminfo-based ANSI escape string to stdout.
/// The string to write.
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Wasi.cs b/src/libraries/System.Console/src/System/ConsolePal.Wasi.cs
index 4022de1a439fe6..70aec828947c03 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Wasi.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Wasi.cs
@@ -20,20 +20,28 @@ internal static partial class ConsolePal
{
public static Stream OpenStandardInput()
{
- return new UnixConsoleStream(Interop.Sys.FileDescriptors.STDIN_FILENO, FileAccess.Read,
+ return new UnixConsoleStream(OpenStandardInputHandle(), FileAccess.Read,
useReadLine: !Console.IsInputRedirected);
}
public static Stream OpenStandardOutput()
{
- return new UnixConsoleStream(Interop.Sys.FileDescriptors.STDOUT_FILENO, FileAccess.Write);
+ return new UnixConsoleStream(OpenStandardOutputHandle(), FileAccess.Write);
}
public static Stream OpenStandardError()
{
- return new UnixConsoleStream(Interop.Sys.FileDescriptors.STDERR_FILENO, FileAccess.Write);
+ return new UnixConsoleStream(OpenStandardErrorHandle(), FileAccess.Write);
}
+ public static SafeFileHandle OpenStandardInputHandle() => OpenStandardHandle(0);
+
+ public static SafeFileHandle OpenStandardOutputHandle() => OpenStandardHandle(1);
+
+ public static SafeFileHandle OpenStandardErrorHandle() => OpenStandardHandle(2);
+
+ private static SafeFileHandle OpenStandardHandle(IntPtr fd) => new SafeFileHandle(fd, ownsHandle: false);
+
public static Encoding InputEncoding
{
get { return GetConsoleEncoding(); }
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs
index 76573cb18eccbc..64b1acc8e83966 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs
@@ -5,6 +5,7 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
+using Microsoft.Win32.SafeHandles;
namespace System
{
@@ -90,6 +91,18 @@ private static unsafe bool ConsoleHandleIsWritable(IntPtr outErrHandle)
return r != 0; // In Win32 apps w/ no console, bResult should be 0 for failure.
}
+ public static SafeFileHandle OpenStandardInputHandle() => OpenStandardHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE);
+
+ public static SafeFileHandle OpenStandardOutputHandle() => OpenStandardHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE);
+
+ public static SafeFileHandle OpenStandardErrorHandle() => OpenStandardHandle(Interop.Kernel32.HandleTypes.STD_ERROR_HANDLE);
+
+ private static SafeFileHandle OpenStandardHandle(int handleType)
+ {
+ IntPtr handle = Interop.Kernel32.GetStdHandle(handleType);
+ return new SafeFileHandle(handle, ownsHandle: false);
+ }
+
public static Encoding InputEncoding
{
get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.Kernel32.GetConsoleCP()); }
diff --git a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
index 5360134bdc108d..223c91d2eba732 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.Text;
+using Microsoft.Win32.SafeHandles;
#pragma warning disable IDE0060
@@ -34,6 +35,12 @@ internal static void EnsureConsoleInitialized()
public static Stream OpenStandardError() => new NSLogStream(OutputEncoding);
+ public static SafeFileHandle OpenStandardInputHandle() => throw new PlatformNotSupportedException();
+
+ public static SafeFileHandle OpenStandardOutputHandle() => throw new PlatformNotSupportedException();
+
+ public static SafeFileHandle OpenStandardErrorHandle() => throw new PlatformNotSupportedException();
+
public static Encoding InputEncoding => throw new PlatformNotSupportedException();
public static void SetConsoleInputEncoding(Encoding enc) => throw new PlatformNotSupportedException();
diff --git a/src/libraries/System.Console/tests/ConsoleHandles.cs b/src/libraries/System.Console/tests/ConsoleHandles.cs
new file mode 100644
index 00000000000000..b09c94b71497c8
--- /dev/null
+++ b/src/libraries/System.Console/tests/ConsoleHandles.cs
@@ -0,0 +1,110 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.IO;
+using Microsoft.DotNet.RemoteExecutor;
+using Microsoft.Win32.SafeHandles;
+using Xunit;
+
+namespace System.Tests
+{
+ public partial class ConsoleTests
+ {
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Any & ~TestPlatforms.Browser & ~TestPlatforms.iOS & ~TestPlatforms.tvOS & ~TestPlatforms.Android)]
+ public void OpenStandardInputHandle_ReturnsValidHandle()
+ {
+ using SafeFileHandle inputHandle = Console.OpenStandardInputHandle();
+ Assert.NotNull(inputHandle);
+ Assert.False(inputHandle.IsInvalid);
+ Assert.False(inputHandle.IsClosed);
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Any & ~TestPlatforms.iOS & ~TestPlatforms.tvOS & ~TestPlatforms.Android)]
+ public void OpenStandardOutputHandle_ReturnsValidHandle()
+ {
+ using SafeFileHandle outputHandle = Console.OpenStandardOutputHandle();
+ Assert.NotNull(outputHandle);
+ Assert.False(outputHandle.IsInvalid);
+ Assert.False(outputHandle.IsClosed);
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Any & ~TestPlatforms.iOS & ~TestPlatforms.tvOS & ~TestPlatforms.Android)]
+ public void OpenStandardErrorHandle_ReturnsValidHandle()
+ {
+ using SafeFileHandle errorHandle = Console.OpenStandardErrorHandle();
+ Assert.NotNull(errorHandle);
+ Assert.False(errorHandle.IsInvalid);
+ Assert.False(errorHandle.IsClosed);
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Any & ~TestPlatforms.Browser & ~TestPlatforms.iOS & ~TestPlatforms.tvOS & ~TestPlatforms.Android)]
+ public void OpenStandardHandles_DoNotOwnHandle()
+ {
+ SafeFileHandle inputHandle = Console.OpenStandardInputHandle();
+ SafeFileHandle outputHandle = Console.OpenStandardOutputHandle();
+ SafeFileHandle errorHandle = Console.OpenStandardErrorHandle();
+
+ // Disposing should not close the underlying handle since ownsHandle is false
+ inputHandle.Dispose();
+ outputHandle.Dispose();
+ errorHandle.Dispose();
+
+ // Should still be able to get new handles
+ using SafeFileHandle inputHandle2 = Console.OpenStandardInputHandle();
+ using SafeFileHandle outputHandle2 = Console.OpenStandardOutputHandle();
+ using SafeFileHandle errorHandle2 = Console.OpenStandardErrorHandle();
+
+ Assert.NotNull(inputHandle2);
+ Assert.NotNull(outputHandle2);
+ Assert.NotNull(errorHandle2);
+ Assert.False(inputHandle2.IsInvalid);
+ Assert.False(outputHandle2.IsInvalid);
+ Assert.False(errorHandle2.IsInvalid);
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ [PlatformSpecific(TestPlatforms.Any & ~TestPlatforms.Browser & ~TestPlatforms.iOS & ~TestPlatforms.tvOS & ~TestPlatforms.Android)]
+ public void OpenStandardHandles_CanBeUsedWithStream()
+ {
+ using RemoteInvokeHandle child = RemoteExecutor.Invoke(() =>
+ {
+ using SafeFileHandle outputHandle = Console.OpenStandardOutputHandle();
+ using FileStream fs = new FileStream(outputHandle, FileAccess.Write);
+ using StreamWriter writer = new StreamWriter(fs);
+ writer.WriteLine("Test output");
+ }, new RemoteInvokeOptions { StartInfo = new ProcessStartInfo() { RedirectStandardOutput = true } });
+
+ // Verify the output was written
+ string output = child.Process.StandardOutput.ReadLine();
+ Assert.Equal("Test output", output);
+
+ child.Process.WaitForExit();
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Android | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Browser)]
+ public void OpenStandardInputHandle_ThrowsOnUnsupportedPlatforms()
+ {
+ Assert.Throws(() => Console.OpenStandardInputHandle());
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Android | TestPlatforms.iOS | TestPlatforms.tvOS)]
+ public void OpenStandardOutputHandle_ThrowsOnUnsupportedPlatforms()
+ {
+ Assert.Throws(() => Console.OpenStandardOutputHandle());
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Android | TestPlatforms.iOS | TestPlatforms.tvOS)]
+ public void OpenStandardErrorHandle_ThrowsOnUnsupportedPlatforms()
+ {
+ Assert.Throws(() => Console.OpenStandardErrorHandle());
+ }
+ }
+}