ReadKey(ReadKeyOptions options) { if ((options & (ReadKeyOptions.IncludeKeyDown | ReadKeyOptions.IncludeKeyUp)) == 0) { throw PSTraceSource.NewArgumentException("options", ConsoleHostRawUserInterfaceStrings.InvalidReadKeyOptionsError); } // keyInfo is initialized in the below if-else statement KeyInfo keyInfo; if (cachedKeyEvent.RepeatCount > 0) { // Ctrl-C is not allowed and Ctrl-C is cached. if (((options & ReadKeyOptions.AllowCtrlC) == 0) && cachedKeyEvent.UnicodeChar == (char)3) { // Ctrl-C is in the cache, stop pipeline immediately cachedKeyEvent.RepeatCount--; throw NewPipelineStoppedException(); } // If IncludeKeyUp is not set and cached key events are KeyUp OR // IncludeKeyDown is not set and cached key events are KeyDown, clear the cache if ((((options & ReadKeyOptions.IncludeKeyUp) == 0) && !cachedKeyEvent.KeyDown) || (((options & ReadKeyOptions.IncludeKeyDown) == 0) && cachedKeyEvent.KeyDown)) { cachedKeyEvent.RepeatCount = 0; } } if (cachedKeyEvent.RepeatCount > 0) { KEY_EVENT_RECORDToKeyInfo(cachedKeyEvent, out keyInfo); cachedKeyEvent.RepeatCount--; } else { ConsoleHandle handle = ConsoleControl.GetConioDeviceHandle(); ConsoleControl.INPUT_RECORD[] inputRecords = new ConsoleControl.INPUT_RECORD[1]; ConsoleControl.ConsoleModes originalMode = ConsoleControl.GetMode(handle); // set input mode to exclude mouse or window events // turn off ProcessedInput flag to handle ctrl-c ConsoleControl.ConsoleModes newMode = originalMode & ~ConsoleControl.ConsoleModes.WindowInput & ~ConsoleControl.ConsoleModes.MouseInput & ~ConsoleControl.ConsoleModes.ProcessedInput; try { ConsoleControl.SetMode(handle, newMode); while (true) { int actualNumberOfInput = ConsoleControl.ReadConsoleInput(handle, ref inputRecords); Dbg.Assert(actualNumberOfInput == 1, string.Format(CultureInfo.InvariantCulture, "ReadConsoleInput returns {0} number of input event records", actualNumberOfInput)); if (actualNumberOfInput == 1) { if (((ConsoleControl.InputRecordEventTypes)inputRecords[0].EventType) == ConsoleControl.InputRecordEventTypes.KEY_EVENT) { Dbg.Assert((inputRecords[0].KeyEvent.KeyDown && inputRecords[0].KeyEvent.RepeatCount != 0) || !inputRecords[0].KeyEvent.KeyDown, string.Format(CultureInfo.InvariantCulture, "ReadConsoleInput returns a KeyEvent that is KeyDown and RepeatCount 0")); if (inputRecords[0].KeyEvent.RepeatCount == 0) { // Sometimes Win32 ReadConsoleInput returns a KeyEvent record whose // RepeatCount is zero. This type of record does not // represent a keystroke. continue; } // Ctrl-C is not allowed and Ctrl-C is input if ((options & ReadKeyOptions.AllowCtrlC) == 0 && inputRecords[0].KeyEvent.UnicodeChar == (char)3) { CacheKeyEvent(inputRecords[0].KeyEvent, ref cachedKeyEvent); throw NewPipelineStoppedException(); } // if KeyDown events are wanted and event is KeyDown OR // KeyUp events are wanted and event is KeyUp if ((((options & ReadKeyOptions.IncludeKeyDown) != 0) && inputRecords[0].KeyEvent.KeyDown) || (((options & ReadKeyOptions.IncludeKeyUp) != 0) && !inputRecords[0].KeyEvent.KeyDown)) { CacheKeyEvent(inputRecords[0].KeyEvent, ref cachedKeyEvent); KEY_EVENT_RECORDToKeyInfo(inputRecords[0].KeyEvent, out keyInfo); break; } } } } } finally { ConsoleControl.SetMode(handle, originalMode); } } if ((options & ReadKeyOptions.NoEcho) == 0) { parent.WriteToConsole( keyInfo.Character.ToString(), true); } return keyInfo; }
public override KeyInfo ReadKey(ReadKeyOptions options) { KeyInfo keyInfo; if ((options & (ReadKeyOptions.IncludeKeyDown | ReadKeyOptions.IncludeKeyUp)) != 0) { if (this.cachedKeyEvent.RepeatCount > 0) { if ((options & ReadKeyOptions.AllowCtrlC) != 0 || this.cachedKeyEvent.UnicodeChar != '\u0003') { if ((options & ReadKeyOptions.IncludeKeyUp) == 0 && !this.cachedKeyEvent.KeyDown || (options & ReadKeyOptions.IncludeKeyDown) == 0 && this.cachedKeyEvent.KeyDown) { this.cachedKeyEvent.RepeatCount = 0; } } else { ConsoleControl.KEY_EVENT_RECORD kEYEVENTRECORDPointer = this.cachedKeyEvent; this.cachedKeyEvent.RepeatCount = (ushort)(this.cachedKeyEvent.RepeatCount - 1); throw this.NewPipelineStoppedException(); } } if (this.cachedKeyEvent.RepeatCount <= 0) { SafeFileHandle inputHandle = ConsoleControl.GetInputHandle(); ConsoleControl.INPUT_RECORD[] nPUTRECORDArray = new ConsoleControl.INPUT_RECORD[1]; ConsoleControl.ConsoleModes mode = ConsoleControl.GetMode(inputHandle); ConsoleControl.ConsoleModes consoleMode = mode & (ConsoleControl.ConsoleModes.ProcessedInput | ConsoleControl.ConsoleModes.LineInput | ConsoleControl.ConsoleModes.EchoInput | ConsoleControl.ConsoleModes.MouseInput | ConsoleControl.ConsoleModes.Insert | ConsoleControl.ConsoleModes.QuickEdit | ConsoleControl.ConsoleModes.Extended | ConsoleControl.ConsoleModes.AutoPosition | ConsoleControl.ConsoleModes.ProcessedOutput | ConsoleControl.ConsoleModes.WrapEndOfLine) & (ConsoleControl.ConsoleModes.ProcessedInput | ConsoleControl.ConsoleModes.LineInput | ConsoleControl.ConsoleModes.EchoInput | ConsoleControl.ConsoleModes.WindowInput | ConsoleControl.ConsoleModes.Insert | ConsoleControl.ConsoleModes.QuickEdit | ConsoleControl.ConsoleModes.Extended | ConsoleControl.ConsoleModes.AutoPosition | ConsoleControl.ConsoleModes.ProcessedOutput | ConsoleControl.ConsoleModes.WrapEndOfLine) & (ConsoleControl.ConsoleModes.LineInput | ConsoleControl.ConsoleModes.EchoInput | ConsoleControl.ConsoleModes.WindowInput | ConsoleControl.ConsoleModes.MouseInput | ConsoleControl.ConsoleModes.Insert | ConsoleControl.ConsoleModes.QuickEdit | ConsoleControl.ConsoleModes.Extended | ConsoleControl.ConsoleModes.AutoPosition | ConsoleControl.ConsoleModes.WrapEndOfLine); try { ConsoleControl.SetMode(inputHandle, consoleMode); do { Label0: int num = ConsoleControl.ReadConsoleInput(inputHandle, ref nPUTRECORDArray); if (num == 1 && nPUTRECORDArray[0].EventType == 1 && nPUTRECORDArray[0].KeyEvent.RepeatCount != 0) { if ((options & ReadKeyOptions.AllowCtrlC) != 0 || nPUTRECORDArray[0].KeyEvent.UnicodeChar != '\u0003') { continue; } ConsoleHostRawUserInterface.CacheKeyEvent(nPUTRECORDArray[0].KeyEvent, ref this.cachedKeyEvent); throw this.NewPipelineStoppedException(); } else { goto Label0; } } while (((options & ReadKeyOptions.IncludeKeyDown) == 0 || !nPUTRECORDArray[0].KeyEvent.KeyDown) && ((options & ReadKeyOptions.IncludeKeyUp) == 0 || nPUTRECORDArray[0].KeyEvent.KeyDown)); ConsoleHostRawUserInterface.CacheKeyEvent(nPUTRECORDArray[0].KeyEvent, ref this.cachedKeyEvent); ConsoleHostRawUserInterface.KEY_EVENT_RECORDToKeyInfo(nPUTRECORDArray[0].KeyEvent, out keyInfo); } finally { ConsoleControl.SetMode(inputHandle, mode); } } else { ConsoleHostRawUserInterface.KEY_EVENT_RECORDToKeyInfo(this.cachedKeyEvent, out keyInfo); this.cachedKeyEvent.RepeatCount = (ushort)(this.cachedKeyEvent.RepeatCount - 1); } if ((options & ReadKeyOptions.NoEcho) == 0) { char character = keyInfo.Character; this.parent.WriteToConsole(character.ToString(CultureInfo.CurrentCulture), true); } return keyInfo; } else { throw PSTraceSource.NewArgumentException("options", "ConsoleHostRawUserInterfaceStrings", "InvalidReadKeyOptionsError", new object[0]); } }