39 protected override void Dispose(
bool disposing)
42 base.Dispose(disposing);
86 flag = global::Interop.Kernel32.ReadFile(hFile, ptr,
buffer.Length, out bytesRead,
IntPtr.
Zero) != 0;
90 flag = global::Interop.Kernel32.ReadConsole(hFile, ptr,
buffer.Length / 2, out var lpNumberOfCharsRead,
IntPtr.
Zero);
91 bytesRead = lpNumberOfCharsRead * 2;
99 if (lastPInvokeError == 232 || lastPInvokeError == 109)
103 return lastPInvokeError;
113 fixed (
byte* ptr =
bytes)
115 flag = ((!useFileAPIs) ? global::Interop.Kernel32.WriteConsole(hFile, ptr,
bytes.Length / 2, out var _,
IntPtr.
Zero) : (global::Interop.Kernel32.WriteFile(hFile, ptr,
bytes.Length, out var _,
IntPtr.
Zero) != 0));
122 if (lastPInvokeError == 232 || lastPInvokeError == 109)
126 return lastPInvokeError;
156 short keyState = global::Interop.User32.GetKeyState(144);
157 return (keyState & 1) == 1;
172 short keyState = global::Interop.User32.GetKeyState(20);
173 return (keyState & 1) == 1;
190 global::Interop.InputRecord
buffer =
default(global::Interop.InputRecord);
191 int numEventsRead = 0;
194 if (!global::Interop.Kernel32.PeekConsoleInput(
InputHandle, out
buffer, 1, out numEventsRead))
197 if (lastPInvokeError == 6)
203 if (numEventsRead == 0)
211 if (!global::Interop.Kernel32.ReadConsoleInput(
InputHandle, out
buffer, 1, out numEventsRead))
230 if (!global::Interop.Kernel32.GetConsoleMode(inputHandle, out mode))
234 return (mode & 1) == 0;
244 if (!global::Interop.Kernel32.GetConsoleMode(inputHandle, out mode))
248 mode = ((!
value) ? (mode | 1) : (mode & -2));
249 if (!global::Interop.Kernel32.SetConsoleMode(inputHandle, mode))
261 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo(throwOnNoConsole:
false, out succeeded);
272 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo(throwOnNoConsole:
false, out succeeded);
275 short wAttributes = bufferInfo.wAttributes;
277 wAttributes = (
short)((ushort)wAttributes | (ushort)color);
278 global::Interop.Kernel32.SetConsoleTextAttribute(
OutputHandle, wAttributes);
288 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo(throwOnNoConsole:
false, out succeeded);
299 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo(throwOnNoConsole:
false, out succeeded);
302 short wAttributes = bufferInfo.wAttributes;
304 wAttributes = (
short)((ushort)wAttributes | (ushort)color);
305 global::Interop.Kernel32.SetConsoleTextAttribute(
OutputHandle, wAttributes);
314 if (!global::Interop.Kernel32.GetConsoleCursorInfo(
OutputHandle, out var cci))
322 if (value < 1 || value > 100)
326 if (!global::Interop.Kernel32.GetConsoleCursorInfo(
OutputHandle, out var cci))
331 if (!global::Interop.Kernel32.SetConsoleCursorInfo(
OutputHandle, ref cci))
342 if (!global::Interop.Kernel32.GetConsoleCursorInfo(
OutputHandle, out var cci))
350 if (!global::Interop.Kernel32.GetConsoleCursorInfo(
OutputHandle, out var cci))
354 cci.bVisible =
value;
355 if (!global::Interop.Kernel32.SetConsoleCursorInfo(
OutputHandle, ref cci))
366 Span<char> initialBuffer = stackalloc
char[256];
372 fixed (
char* title = valueStringBuilder)
374 num = global::Interop.Kernel32.GetConsoleTitleW(title, (uint)valueStringBuilder.
Capacity);
379 switch (lastPInvokeError)
397 valueStringBuilder.Length = (int)num;
398 return valueStringBuilder.
ToString();
402 if (!global::Interop.Kernel32.SetConsoleTitle(
value))
465 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
466 return bufferInfo.srWindow.Right - bufferInfo.srWindow.Left + 1;
478 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
479 return bufferInfo.srWindow.Bottom - bufferInfo.srWindow.Top + 1;
494 if (version.
Major == 6)
496 return version.Minor == 1;
518 IntPtr stdHandle = global::Interop.Kernel32.GetStdHandle(handleType);
530 int num = global::Interop.Kernel32.WriteFile(outErrHandle, &b, 0, out numBytesWritten,
IntPtr.
Zero);
536 if (enc.
CodePage != 1200 && !global::Interop.Kernel32.SetConsoleCP(enc.
CodePage))
544 if (enc.
CodePage != 1200 && !global::Interop.Kernel32.SetConsoleOutputCP(enc.
CodePage))
567 uint fileType = global::Interop.Kernel32.GetFileType(
handle);
568 if ((fileType & 2) != 2)
572 return !global::Interop.Kernel32.IsGetConsoleModeCallSuccessful(
handle);
583 if (ir.eventType == 1)
585 return ir.keyEvent.keyDown != global::Interop.BOOL.FALSE;
590 private static bool IsModKey(global::Interop.InputRecord ir)
592 short virtualKeyCode = ir.keyEvent.virtualKeyCode;
593 if ((virtualKeyCode < 16 || virtualKeyCode > 18) && virtualKeyCode != 20 && virtualKeyCode != 144)
595 return virtualKeyCode == 145;
602 return (ir.keyEvent.controlKeyState & 3) != 0;
607 int numEventsRead = -1;
608 global::Interop.InputRecord
buffer;
616 _cachedInputRecord.eventType = -1;
627 if (!global::Interop.Kernel32.ReadConsoleInput(
InputHandle, out
buffer, 1, out numEventsRead) || numEventsRead == 0)
631 short virtualKeyCode =
buffer.keyEvent.virtualKeyCode;
641 if (consoleKey < ConsoleKey.NumPad0 || consoleKey >
ConsoleKey.NumPad9)
660 if (
buffer.keyEvent.repeatCount > 1)
662 buffer.keyEvent.repeatCount--;
669 bool alt = (controlKeyState & (ControlKeyState.RightAltPressed |
ControlKeyState.LeftAltPressed)) != 0;
670 bool control = (controlKeyState & (ControlKeyState.RightCtrlPressed |
ControlKeyState.LeftCtrlPressed)) != 0;
694 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
695 return (
Left: bufferInfo.dwCursorPosition.X, Top: bufferInfo.dwCursorPosition.Y);
700 global::Interop.Kernel32.Beep(800, 200);
703 public static void Beep(
int frequency,
int duration)
705 if (frequency < 37 || frequency > 32767)
713 global::Interop.Kernel32.Beep(frequency, duration);
716 public unsafe
static void MoveBufferArea(
int sourceLeft,
int sourceTop,
int sourceWidth,
int sourceHeight,
int targetLeft,
int targetTop,
char sourceChar,
ConsoleColor sourceForeColor,
ConsoleColor sourceBackColor)
718 if (sourceForeColor < ConsoleColor.Black || sourceForeColor >
ConsoleColor.White)
722 if (sourceBackColor < ConsoleColor.Black || sourceBackColor >
ConsoleColor.White)
726 global::Interop.Kernel32.COORD dwSize =
GetBufferInfo().dwSize;
727 if (sourceLeft < 0 || sourceLeft > dwSize.X)
731 if (sourceTop < 0 || sourceTop > dwSize.Y)
735 if (sourceWidth < 0 || sourceWidth > dwSize.X - sourceLeft)
739 if (sourceHeight < 0 || sourceTop > dwSize.Y - sourceHeight)
743 if (targetLeft < 0 || targetLeft > dwSize.X)
747 if (targetTop < 0 || targetTop > dwSize.Y)
751 if (sourceWidth == 0 || sourceHeight == 0)
755 global::Interop.Kernel32.CHAR_INFO[]
array =
new global::Interop.Kernel32.CHAR_INFO[sourceWidth * sourceHeight];
756 dwSize.X = (
short)sourceWidth;
757 dwSize.Y = (
short)sourceHeight;
758 global::Interop.Kernel32.COORD bufferCoord =
default(global::Interop.Kernel32.COORD);
759 global::Interop.Kernel32.SMALL_RECT readRegion =
default(global::Interop.Kernel32.SMALL_RECT);
760 readRegion.Left = (
short)sourceLeft;
761 readRegion.Right = (
short)(sourceLeft + sourceWidth - 1);
762 readRegion.Top = (
short)sourceTop;
763 readRegion.Bottom = (
short)(sourceTop + sourceHeight - 1);
765 fixed (global::Interop.Kernel32.CHAR_INFO* pBuffer =
array)
767 flag = global::Interop.Kernel32.ReadConsoleOutput(
OutputHandle, pBuffer, dwSize, bufferCoord, ref readRegion);
773 global::Interop.Kernel32.COORD cOORD =
default(global::Interop.Kernel32.COORD);
774 cOORD.X = (
short)sourceLeft;
777 short wColorAttribute = (
short)color;
778 for (
int i = sourceTop; i < sourceTop + sourceHeight; i++)
781 if (!global::Interop.Kernel32.FillConsoleOutputCharacter(
OutputHandle, sourceChar, sourceWidth, cOORD, out var pNumCharsWritten))
785 if (!global::Interop.Kernel32.FillConsoleOutputAttribute(
OutputHandle, wColorAttribute, sourceWidth, cOORD, out pNumCharsWritten))
790 global::Interop.Kernel32.SMALL_RECT writeRegion =
default(global::Interop.Kernel32.SMALL_RECT);
791 writeRegion.Left = (
short)targetLeft;
792 writeRegion.Right = (
short)(targetLeft + sourceWidth);
793 writeRegion.Top = (
short)targetTop;
794 writeRegion.Bottom = (
short)(targetTop + sourceHeight);
795 fixed (global::Interop.Kernel32.CHAR_INFO*
buffer =
array)
797 global::Interop.Kernel32.WriteConsoleOutput(
OutputHandle,
buffer, dwSize, bufferCoord, ref writeRegion);
803 global::Interop.Kernel32.COORD cOORD =
default(global::Interop.Kernel32.COORD);
809 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
810 int num = bufferInfo.dwSize.X * bufferInfo.dwSize.Y;
811 int pNumCharsWritten = 0;
812 if (!global::Interop.Kernel32.FillConsoleOutputCharacter(outputHandle,
' ', num, cOORD, out pNumCharsWritten))
816 pNumCharsWritten = 0;
817 if (!global::Interop.Kernel32.FillConsoleOutputAttribute(outputHandle, bufferInfo.wAttributes, num, cOORD, out pNumCharsWritten))
821 if (!global::Interop.Kernel32.SetConsoleCursorPosition(outputHandle, cOORD))
830 global::Interop.Kernel32.COORD cursorPosition =
default(global::Interop.Kernel32.COORD);
831 cursorPosition.X = (
short)left;
832 cursorPosition.Y = (
short)top;
833 if (!global::Interop.Kernel32.SetConsoleCursorPosition(outputHandle, cursorPosition))
836 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
837 if (left >= bufferInfo.dwSize.X)
841 if (top >= bufferInfo.dwSize.Y)
851 global::Interop.Kernel32.SMALL_RECT srWindow =
GetBufferInfo().srWindow;
852 if (width < srWindow.Right + 1 || width >= 32767)
856 if (height < srWindow.Bottom + 1 || height >= 32767)
860 global::Interop.Kernel32.COORD size =
default(global::Interop.Kernel32.COORD);
861 size.X = (
short)width;
862 size.Y = (
short)height;
863 if (!global::Interop.Kernel32.SetConsoleScreenBufferSize(
OutputHandle, size))
871 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
872 global::Interop.Kernel32.SMALL_RECT srWindow = bufferInfo.srWindow;
873 int num = left + srWindow.Right - srWindow.Left;
874 if (left < 0 || num > bufferInfo.dwSize.X - 1 || num < left)
878 int num2 = top + srWindow.Bottom - srWindow.Top;
879 if (top < 0 || num2 > bufferInfo.dwSize.Y - 1 || num2 < top)
883 srWindow.Bottom = (
short)num2;
884 srWindow.Right = (
short)num;
885 srWindow.Left = (
short)left;
886 srWindow.Top = (
short)top;
887 if (!global::Interop.Kernel32.SetConsoleWindowInfo(
OutputHandle, absolute:
true, &srWindow))
903 global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
GetBufferInfo();
905 global::Interop.Kernel32.COORD size =
default(global::Interop.Kernel32.COORD);
906 size.X = bufferInfo.dwSize.X;
907 size.Y = bufferInfo.dwSize.Y;
908 if (bufferInfo.dwSize.X < bufferInfo.srWindow.Left + width)
910 if (bufferInfo.srWindow.Left >= 32767 - width)
914 size.X = (
short)(bufferInfo.srWindow.Left + width);
917 if (bufferInfo.dwSize.Y < bufferInfo.srWindow.Top + height)
919 if (bufferInfo.srWindow.Top >= 32767 - height)
923 size.Y = (
short)(bufferInfo.srWindow.Top + height);
926 if (flag && !global::Interop.Kernel32.SetConsoleScreenBufferSize(
OutputHandle, size))
930 global::Interop.Kernel32.SMALL_RECT srWindow = bufferInfo.srWindow;
931 srWindow.Bottom = (
short)(srWindow.Top + height - 1);
932 srWindow.Right = (
short)(srWindow.Left + width - 1);
933 if (!global::Interop.Kernel32.SetConsoleWindowInfo(
OutputHandle, absolute:
true, &srWindow))
938 global::Interop.Kernel32.SetConsoleScreenBufferSize(
OutputHandle, bufferInfo.dwSize);
940 global::Interop.Kernel32.COORD largestConsoleWindowSize = global::Interop.Kernel32.GetLargestConsoleWindowSize(
OutputHandle);
941 if (width > largestConsoleWindowSize.X)
945 if (height > largestConsoleWindowSize.Y)
955 if (((uint)color & 0xFFFFFFF0u) != 0)
959 global::Interop.Kernel32.Color color2 = (global::Interop.Kernel32.Color)color;
962 color2 = (global::Interop.Kernel32.Color)((
int)color2 << 4);
969 if ((c & global::Interop.Kernel32.Color.BackgroundMask) != 0)
971 c = (global::Interop.Kernel32.Color)((
int)c >> 4);
976 private static global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
GetBufferInfo()
982 private static global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
GetBufferInfo(
bool throwOnNoConsole, out
bool succeeded)
988 if (throwOnNoConsole)
992 return default(global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO);
994 if (!global::Interop.Kernel32.GetConsoleScreenBufferInfo(outputHandle, out var lpConsoleScreenBufferInfo) && !global::Interop.Kernel32.GetConsoleScreenBufferInfo(
ErrorHandle, out lpConsoleScreenBufferInfo) && !global::Interop.Kernel32.GetConsoleScreenBufferInfo(
InputHandle, out lpConsoleScreenBufferInfo))
997 if (lastPInvokeError == 6 && !throwOnNoConsole)
999 return default(global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO);
1005 _defaultColors = (byte)((uint)lpConsoleScreenBufferInfo.wAttributes & 0xFFu);
1009 return lpConsoleScreenBufferInfo;
WindowsConsoleStream(IntPtr handle, FileAccess access, bool useFileAPIs)
override int Read(Span< byte > buffer)
static unsafe int ReadFileNative(IntPtr hFile, Span< byte > buffer, bool isPipe, out int bytesRead, bool useFileAPIs)
override void Write(ReadOnlySpan< byte > buffer)
override void Dispose(bool disposing)
static unsafe int WriteFileNative(IntPtr hFile, ReadOnlySpan< byte > bytes, bool useFileAPIs)
readonly bool _useFileAPIs
static bool TreatControlCAsInput
static bool IsOutputRedirectedCore()
static global::Interop.Kernel32.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground)
static Encoding InputEncoding
static IntPtr ErrorHandle
static volatile byte _defaultColors
static int int Top GetCursorPosition()
static bool CursorVisible
static ConsoleColor ColorAttributeToConsoleColor(global::Interop.Kernel32.Color c)
static bool IsModKey(global::Interop.InputRecord ir)
static IntPtr InvalidHandleValue
static void SetBufferSize(int width, int height)
static bool IsHandleRedirected(IntPtr handle)
static unsafe bool ConsoleHandleIsWritable(IntPtr outErrHandle)
static IntPtr InputHandle
static unsafe string Title
static IntPtr OutputHandle
static Stream OpenStandardInput()
static volatile bool _haveReadDefaultColors
static bool IsAltKeyDown(global::Interop.InputRecord ir)
static void SetConsoleOutputEncoding(Encoding enc)
static void EnsureConsoleInitialized()
static int LargestWindowHeight
static Stream OpenStandardError()
static unsafe void SetWindowPosition(int left, int top)
static TextReader GetOrCreateReader()
static readonly object s_readKeySyncObject
static Stream GetStandardFile(int handleType, FileAccess access, bool useFileAPIs)
static int LargestWindowWidth
static bool IsErrorRedirectedCore()
static unsafe void SetWindowSize(int width, int height)
static ConsoleColor ForegroundColor
static Stream OpenStandardOutput()
static global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(bool throwOnNoConsole, out bool succeeded)
static void SetCursorPosition(int left, int top)
static Encoding OutputEncoding
static bool IsInputRedirectedCore()
static void Beep(int frequency, int duration)
static global::Interop.Kernel32.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo()
static bool IsKeyDownEvent(global::Interop.InputRecord ir)
static ConsoleKeyInfo ReadKey(bool intercept)
static unsafe void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop, char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
static void SetConsoleInputEncoding(Encoding enc)
static ConsoleColor BackgroundColor
static global::Interop.InputRecord _cachedInputRecord
static void Write(string format, object? arg0)
static bool IsInputRedirected
static Encoding InputEncoding
static bool IsErrorRedirected
static Encoding OutputEncoding
static bool IsOutputRedirected
static OperatingSystem OSVersion
static Exception GetFileNotOpen()
static new readonly StreamReader Null
static readonly Stream Null
static SyncTextReader GetSynchronizedTextReader(TextReader reader)
static Exception GetExceptionForWin32Error(int errorCode, string path="")
static int GetLastPInvokeError()
static string ArgumentOutOfRange_NeedPosNum
static string ArgumentOutOfRange_ConsoleWindowSize_Size
static string ArgumentOutOfRange_ConsoleWindowPos
static string ArgumentOutOfRange_BeepFrequency
static string ArgumentOutOfRange_ConsoleWindowBufferSize
static string InvalidOperation_ConsoleKeyAvailableOnFile
static string Format(string resourceFormat, object p1)
static string IO_NoConsole
static string ArgumentOutOfRange_CursorSize
static string InvalidOperation_ConsoleReadKeyOnFile
static string ArgumentOutOfRange_ConsoleBufferBoundaries
static string Arg_InvalidConsoleColor
static string ArgumentOutOfRange_ConsoleBufferLessThanWindowSize
static Encoding GetSupportedConsoleEncoding(int codepage)
static readonly IntPtr Zero
void EnsureCapacity(int capacity)
override string ToString()