Repository: dotnet/runtime
File: src/libraries/System.Console/src/System/ConsolePal.Windows.cs (C#)

Code before:
            // Windows apps may have non-null valid looking handle values for
            // stdin, stdout and stderr, but they may not be readable or
            // writable.  Verify this by calling ReadFile in the
            // appropriate modes. This must handle console-less Windows apps.
            int r = Interop.Kernel32.ReadFile(inHandle, null, 0, out _, IntPtr.Zero);
            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);
            bool isReadable = handleType == Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE;

            // If someone launches a managed process via CreateProcess, stdin/stdout/stderr
            // could be set to INVALID_HANDLE_VALUE or they might use 0 as an invalid handle.
            // We also need to ensure that the handle is readable (for stdin) or writable (for stdout/stderr).
            if (handle == IntPtr.Zero || handle == InvalidHandleValue
                || (isReadable ? !ConsoleHandleIsReadable(handle) : !ConsoleHandleIsWritable(handle)))
            {
                throw new IOException(SR.IO_NoConsole);
            }

            return new SafeFileHandle(handle, ownsHandle: false);
        }

        public static Encoding InputEncoding
        {
            get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.Kernel32.GetConsoleCP()); }
        }

        public static void SetConsoleInputEncoding(Encoding enc)
        {
            if (enc.CodePage != UnicodeCodePage)
            {
                if (!Interop.Kernel32.SetConsoleCP(enc.CodePage))
                {
                    HandleSetConsoleEncodingError(Marshal.GetLastPInvokeError());
                }
            }
        }

        public static Encoding OutputEncoding
        {
            get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.Kernel32.GetConsoleOutputCP()); }
        }

Review comment (suggestion):
Let's make it clear that the handle is invalid. It may require copying the resource string

https://github.com/dotnet/runtime/blob/a6d48ff4f1b42ba935420844ed3234a98fbdca98/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs#L496C22-L496C86

```suggestion
                throw new InvalidOperationException(SR.InvalidOperation_InvalidHandle);
```

Code after:
        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()); }
        }

        public static void SetConsoleInputEncoding(Encoding enc)
        {
            if (enc.CodePage != UnicodeCodePage)
            {
                if (!Interop.Kernel32.SetConsoleCP(enc.CodePage))
                {
                    HandleSetConsoleEncodingError(Marshal.GetLastPInvokeError());
                }
            }
        }

        public static Encoding OutputEncoding
        {
            get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.Kernel32.GetConsoleOutputCP()); }
        }

        public static void SetConsoleOutputEncoding(Encoding enc)
        {
            if (enc.CodePage != UnicodeCodePage)
            {
                if (!Interop.Kernel32.SetConsoleOutputCP(enc.CodePage))
                {
                    HandleSetConsoleEncodingError(Marshal.GetLastPInvokeError());
                }
            }
        }

        private static void HandleSetConsoleEncodingError(int lastError)
        {
            if (lastError == Interop.Errors.ERROR_INVALID_HANDLE
                || lastError == Interop.Errors.ERROR_INVALID_ACCESS)
            {
                // no console, or not a valid handle, so fail silently
                return;
            }

            throw Win32Marshal.GetExceptionForWin32Error(lastError);
        }