Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Console.cs / 4 / Console.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: Console ** ** ** Purpose: This class provides access to the standard input, standard output ** and standard error streams. ** ** =============================================================================*/ namespace System { using System; using System.IO; using System.Text; using System.Globalization; using System.Security.Permissions; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Threading; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; // Provides static fields for console input & output. Use // Console.In for input from the standard input stream (stdin), // Console.Out for output to stdout, and Console.Error // for output to stderr. If any of those console streams are // redirected from the command line, these streams will be redirected. // A program can also redirect its own output or input with the // SetIn, SetOut, and SetError methods. // // The distinction between Console.Out & Console.Error is useful // for programs that redirect output to a file or a pipe. Note that // stdout & stderr can be output to different files at the same // time from the DOS command line: // // someProgram 1> out 2> err // //Contains only static data. Serializable attribute not required. public static class Console { private const int _DefaultConsoleBufferSize = 256; #if !FEATURE_PAL private const int NumberLockVKCode = 0x90; // virtual key code private const int CapsLockVKCode = 0x14; // Beep range - see MSDN. private const int MinBeepFrequency = 37; private const int MaxBeepFrequency = 32767; // MSDN says console titles can be up to 64 KB in length. // But I get an exception if I use buffer lengths longer than // ~24500 Unicode characters. Oh well. private const int MaxConsoleTitleLength = 24500; #endif // !FEATURE_PAL private static TextReader _in; private static TextWriter _out; private static TextWriter _error; private static ConsoleCancelEventHandler _cancelCallbacks; private static ControlC---- _----; #if !FEATURE_PAL // ReadLine & Read can't use this because they need to use ReadFile // to be able to handle redirected input. We have to accept that // we will lose repeated keystrokes when someone switches from // calling ReadKey to calling Read or ReadLine. Those methods should // ideally flush this cache as well. private static Win32Native.InputRecord _cachedInputRecord; // For ResetColor private static bool _haveReadDefaultColors; private static byte _defaultColors; #endif // !FEATURE_PAL private static bool _wasOutRedirected; private static bool _wasErrorRedirected; // Private object for locking instead of locking on a public type for SQL reliability work. private static Object s_InternalSyncObject; private static Object InternalSyncObject { get { if (s_InternalSyncObject == null) { Object o = new Object(); Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } return s_InternalSyncObject; } } // About reliability: I'm not using SafeHandle here. We don't // need to close these handles, and we don't allow the user to close // them so we don't have many of the security problems inherent in // something like file handles. Additionally, in a host like SQL // Server, we won't have a console. private static IntPtr _consoleInputHandle; private static IntPtr _consoleOutputHandle; private static IntPtr ConsoleInputHandle { [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] get { if (_consoleInputHandle == IntPtr.Zero) { _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE); } return _consoleInputHandle; } } private static IntPtr ConsoleOutputHandle { [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] get { if (_consoleOutputHandle == IntPtr.Zero) { _consoleOutputHandle = Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE); } return _consoleOutputHandle; } } public static TextWriter Error { [HostProtection(UI=true)] get { // Hopefully this is inlineable. if (_error == null) InitializeStdOutError(false); return _error; } } public static TextReader In { [HostProtection(UI=true)] get { // Because most applications don't use stdin, we can delay // initialize it slightly better startup performance. if (_in == null) { lock(InternalSyncObject) { if (_in == null) { // Set up Console.In Stream s = OpenStandardInput(_DefaultConsoleBufferSize); TextReader tr; if (s == Stream.Null) tr = StreamReader.Null; else { // Hopefully Encoding.GetEncoding doesn't load as many classes now. Encoding enc = Encoding.GetEncoding((int)Win32Native.GetConsoleCP()); tr = TextReader.Synchronized(new StreamReader(s, enc, false, _DefaultConsoleBufferSize, false)); } System.Threading.Thread.MemoryBarrier(); _in = tr; } } } return _in; } } public static TextWriter Out { [HostProtection(UI=true)] get { // Hopefully this is inlineable. if (_out == null) InitializeStdOutError(true); return _out; } } // For console apps, the console handles are set to values like 3, 7, // and 11 OR if you've been created via CreateProcess, possibly -1 // or 0. -1 is definitely invalid, while 0 is probably invalid. // Also // We do not do a security private static void InitializeStdOutError(bool stdout) { // Set up Console.Out or Console.Error. lock(InternalSyncObject) { if (stdout && _out != null) return; else if (!stdout && _error != null) return; TextWriter writer = null; Stream s; if (stdout) s = OpenStandardOutput(_DefaultConsoleBufferSize); else s = OpenStandardError(_DefaultConsoleBufferSize); if (s == Stream.Null) { #if _DEBUG if (CheckOutputDebug()) writer = MakeDebugOutputTextWriter((stdout) ? "Console.Out: " : "Console.Error: "); else #endif // _DEBUG writer = TextWriter.Synchronized(StreamWriter.Null); } else { int codePage = (int) Win32Native.GetConsoleOutputCP(); Encoding encoding = Encoding.GetEncoding(codePage); StreamWriter stdxxx = new StreamWriter(s, encoding, _DefaultConsoleBufferSize, false); stdxxx.HaveWrittenPreamble = true; stdxxx.AutoFlush = true; writer = TextWriter.Synchronized(stdxxx); } if (stdout) _out = writer; else _error = writer; BCLDebug.Assert((stdout && _out != null) || (!stdout && _error != null), "Didn't set Console::_out or _error appropriately!"); } } // This is ONLY used in debug builds. If you have a registry key set, // it will redirect Console.Out & Error on console-less applications to // your debugger's output window. #if _DEBUG [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private static bool CheckOutputDebug() { #if !FEATURE_PAL new System.Security.Permissions.RegistryPermission(RegistryPermissionAccess.Read | RegistryPermissionAccess.Write, "HKEY_LOCAL_MACHINE").Assert(); RegistryKey rk = Registry.LocalMachine; using (rk = rk.OpenSubKey("Software\\Microsoft\\.NETFramework", false)) { if (rk != null) { Object obj = rk.GetValue("ConsoleSpewToDebugger", 0); if (obj != null && ((int)obj) != 0) { return true; } } } return false; #else // !FEATURE_PAL const int parameterValueLength = 255; StringBuilder parameterValue = new StringBuilder(parameterValueLength); bool rc = Win32Native.FetchConfigurationString(true, "ConsoleSpewToDebugger", parameterValue, parameterValueLength); if (rc) { if (0 != parameterValue.Length) { int value = Convert.ToInt32(parameterValue.ToString()); if (0 != value) return true; } } return false; #endif // !FEATURE_PAL } #endif // _DEBUG #if _DEBUG private static TextWriter MakeDebugOutputTextWriter(String streamLabel) { TextWriter output = new __DebugOutputTextWriter(streamLabel); output.WriteLine("Output redirected to debugger from a bit bucket."); return TextWriter.Synchronized(output); } #endif // _DEBUG // This method is only exposed via methods to get at the console. // We won't use any security checks here. [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] private static Stream GetStandardFile(int stdHandleName, FileAccess access, int bufferSize) { // We shouldn't close the handle for stdout, etc, or we'll break // unmanaged code in the process that will print to console. // We should have a better way of marking this on SafeHandle. IntPtr handle = Win32Native.GetStdHandle(stdHandleName); SafeFileHandle sh = new SafeFileHandle(handle, false); // If someone launches a managed process via CreateProcess, stdout // stderr, & stdin could independently be set to INVALID_HANDLE_VALUE. // Additionally they might use 0 as an invalid handle. if (sh.IsInvalid) { // Minor perf optimization - get it out of the finalizer queue. sh.SetHandleAsInvalid(); return Stream.Null; } // Check whether we can read or write to this handle. if (stdHandleName != Win32Native.STD_INPUT_HANDLE && !ConsoleHandleIsValid(sh)) { //BCLDebug.ConsoleError("Console::ConsoleHandleIsValid for std handle "+stdHandleName+" failed, setting it to a null stream"); return Stream.Null; } //BCLDebug.ConsoleError("Console::GetStandardFile for std handle "+stdHandleName+" succeeded, returning handle number "+handle.ToString()); Stream console = new __ConsoleStream(sh, access); // Do not buffer console streams, or we can get into situations where // we end up blocking waiting for you to hit enter twice. It was // redundant. return console; } public static Encoding InputEncoding { get { uint cp = Win32Native.GetConsoleCP(); return Encoding.GetEncoding((int) cp); } set { if (value == null) throw new ArgumentNullException("value"); if (Environment.IsWin9X()) throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); uint cp = (uint) value.CodePage; lock(InternalSyncObject) { bool r = Win32Native.SetConsoleCP(cp); if (!r) __Error.WinIOError(); // We need to reinitialize Console.In in the next call to _in // This will discard the current StreamReader, potentially // losing buffered data _in = null; } } } public static Encoding OutputEncoding { get { uint cp = Win32Native.GetConsoleOutputCP(); return Encoding.GetEncoding((int) cp); } set { if (value == null) throw new ArgumentNullException("value"); if (Environment.IsWin9X()) throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); lock(InternalSyncObject) { // Before changing the code page we need to flush the data // if Out hasn't been redirected. Also, have the next call to // _out reinitialize the console code page. if (_out != null && !_wasOutRedirected) { _out.Flush(); _out = null; } if (_error != null && !_wasErrorRedirected) { _error.Flush(); _error = null; } uint cp = (uint) value.CodePage; bool r = Win32Native.SetConsoleOutputCP(cp); if (!r) __Error.WinIOError(); } } } #if !FEATURE_PAL [HostProtection(UI=true)] public static void Beep() { Beep(800, 200); } [HostProtection(UI=true)] public static void Beep(int frequency, int duration) { if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency) throw new ArgumentOutOfRangeException("frequency", frequency, Environment.GetResourceString("ArgumentOutOfRange_BeepFrequency", MinBeepFrequency, MaxBeepFrequency)); if (duration <= 0) throw new ArgumentOutOfRangeException("duration", duration, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); // Note that Beep over Remote Desktop connections does not currently // work. Ignore any failures here. Win32Native.Beep(frequency, duration); } [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static void Clear() { Win32Native.COORD coordScreen = new Win32Native.COORD(); Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi; bool success; int conSize; IntPtr hConsole = ConsoleOutputHandle; if (hConsole == Win32Native.INVALID_HANDLE_VALUE) throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); // get the number of character cells in the current buffer // Go through my helper method for fetching a screen buffer info // to correctly handle default console colors. csbi = GetBufferInfo(); conSize = csbi.dwSize.X * csbi.dwSize.Y; // fill the entire screen with blanks int numCellsWritten = 0; success = Win32Native.FillConsoleOutputCharacter(hConsole, ' ', conSize, coordScreen, out numCellsWritten); if (!success) __Error.WinIOError(); // now set the buffer's attributes accordingly numCellsWritten = 0; success = Win32Native.FillConsoleOutputAttribute(hConsole, csbi.wAttributes, conSize, coordScreen, out numCellsWritten); if (!success) __Error.WinIOError(); // put the cursor at (0, 0) success = Win32Native.SetConsoleCursorPosition(hConsole, coordScreen); if (!success) __Error.WinIOError(); } private static Win32Native.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground) { if ((((int)color) & ~0xf) != 0) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor")); Win32Native.Color c = (Win32Native.Color) color; // Make these background colors instead of foreground if (isBackground) c = (Win32Native.Color) ((int)c << 4); return c; } private static ConsoleColor ColorAttributeToConsoleColor(Win32Native.Color c) { // Turn background colors into foreground colors. if ((c & Win32Native.Color.BackgroundMask) != 0) c = (Win32Native.Color) (((int)c) >> 4); return (ConsoleColor) c; } public static ConsoleColor BackgroundColor { get { bool succeeded; Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); // For code that may be used from Windows app w/ no console if (!succeeded) return ConsoleColor.Black; Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.BackgroundMask; return ColorAttributeToConsoleColor(c); } set { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); Win32Native.Color c = ConsoleColorToColorAttribute(value, true); bool succeeded; Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); // For code that may be used from Windows app w/ no console if (!succeeded) return; BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); short attrs = csbi.wAttributes; attrs &= ~((short)Win32Native.Color.BackgroundMask); // C#'s bitwise-or sign-extends to 32 bits. attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c)); // Ignore errors here - there are some scenarios for running code that wants // to print in colors to the console in a Windows application. Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs); } } public static ConsoleColor ForegroundColor { get { bool succeeded; Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); // For code that may be used from Windows app w/ no console if (!succeeded) return ConsoleColor.Gray; Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.ForegroundMask; return ColorAttributeToConsoleColor(c); } set { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); Win32Native.Color c = ConsoleColorToColorAttribute(value, false); bool succeeded; Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); // For code that may be used from Windows app w/ no console if (!succeeded) return; BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); short attrs = csbi.wAttributes; attrs &= ~((short)Win32Native.Color.ForegroundMask); // C#'s bitwise-or sign-extends to 32 bits. attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c)); // Ignore errors here - there are some scenarios for running code that wants // to print in colors to the console in a Windows application. Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs); } } public static void ResetColor() { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); bool succeeded; Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); // For code that may be used from Windows app w/ no console if (!succeeded) return; BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); short defaultAttrs = (short) (ushort) _defaultColors; // Ignore errors here - there are some scenarios for running code that wants // to print in colors to the console in a Windows application. Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, defaultAttrs); } public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop) { MoveBufferArea(sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop, ' ', ConsoleColor.Black, BackgroundColor); } public unsafe static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop, char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) { if (sourceForeColor < ConsoleColor.Black || sourceForeColor > ConsoleColor.White) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceForeColor"); if (sourceBackColor < ConsoleColor.Black || sourceBackColor > ConsoleColor.White) throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceBackColor"); Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); Win32Native.COORD bufferSize = csbi.dwSize; if (sourceLeft < 0 || sourceLeft > bufferSize.X) throw new ArgumentOutOfRangeException("sourceLeft", sourceLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (sourceTop < 0 || sourceTop > bufferSize.Y) throw new ArgumentOutOfRangeException("sourceTop", sourceTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (sourceWidth < 0 || sourceWidth > bufferSize.X - sourceLeft) throw new ArgumentOutOfRangeException("sourceWidth", sourceWidth, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (sourceHeight < 0 || sourceTop > bufferSize.Y - sourceHeight) throw new ArgumentOutOfRangeException("sourceHeight", sourceHeight, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); // Note: if the target range is partially in and partially out // of the buffer, then we let the OS clip it for us. if (targetLeft < 0 || targetLeft > bufferSize.X) throw new ArgumentOutOfRangeException("targetLeft", targetLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (targetTop < 0 || targetTop > bufferSize.Y) throw new ArgumentOutOfRangeException("targetTop", targetTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); // If we're not doing any work, bail out now (Windows will return // an error otherwise) if (sourceWidth == 0 || sourceHeight == 0) return; new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); // Read data from the original location, blank it out, then write // it to the new location. This will handle overlapping source and // destination regions correctly. // See the "Reading and Writing Blocks of Characters and Attributes" // sample for help // Read the old data Win32Native.CHAR_INFO[] data = new Win32Native.CHAR_INFO[sourceWidth * sourceHeight]; bufferSize.X = (short) sourceWidth; bufferSize.Y = (short) sourceHeight; Win32Native.COORD bufferCoord = new Win32Native.COORD(); Win32Native.SMALL_RECT readRegion = new Win32Native.SMALL_RECT(); readRegion.Left = (short) sourceLeft; readRegion.Right = (short) (sourceLeft + sourceWidth - 1); readRegion.Top = (short) sourceTop; readRegion.Bottom = (short) (sourceTop + sourceHeight - 1); bool r; fixed(Win32Native.CHAR_INFO* pCharInfo = data) r = Win32Native.ReadConsoleOutput(ConsoleOutputHandle, pCharInfo, bufferSize, bufferCoord, ref readRegion); if (!r) __Error.WinIOError(); // Overwrite old section // I don't have a good function to blank out a rectangle. Win32Native.COORD writeCoord = new Win32Native.COORD(); writeCoord.X = (short) sourceLeft; Win32Native.Color c = ConsoleColorToColorAttribute(sourceBackColor, true); c |= ConsoleColorToColorAttribute(sourceForeColor, false); short attr = (short) c; int numWritten; for(int i = sourceTop; i= Int16.MaxValue) throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize")); if (height < srWindow.Bottom + 1 || height >= Int16.MaxValue) throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize")); Win32Native.COORD size = new Win32Native.COORD(); size.X = (short) width; size.Y = (short) height; bool r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); if (!r) __Error.WinIOError(); } public static int WindowHeight { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } set { SetWindowSize(WindowWidth, value); } } public static int WindowWidth { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.srWindow.Right - csbi.srWindow.Left + 1; } set { SetWindowSize(value, WindowHeight); } } public static unsafe void SetWindowSize(int width, int height) { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); // Get the position of the current console window Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); if (width <= 0) throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); if (height <= 0) throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); bool r; // If the buffer is smaller than this new window size, resize the // buffer to be large enough. Include window position. bool resizeBuffer = false; Win32Native.COORD size = new Win32Native.COORD(); size.X = csbi.dwSize.X; size.Y = csbi.dwSize.Y; if (csbi.dwSize.X < csbi.srWindow.Left + width) { if (csbi.srWindow.Left >= Int16.MaxValue - width) throw new ArgumentOutOfRangeException("width", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); size.X = (short) (csbi.srWindow.Left + width); resizeBuffer = true; } if (csbi.dwSize.Y < csbi.srWindow.Top + height) { if (csbi.srWindow.Top >= Int16.MaxValue - height) throw new ArgumentOutOfRangeException("height", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); size.Y = (short) (csbi.srWindow.Top + height); resizeBuffer = true; } if (resizeBuffer) { r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); if (!r) __Error.WinIOError(); } Win32Native.SMALL_RECT srWindow = csbi.srWindow; // Preserve the position, but change the size. srWindow.Bottom = (short) (srWindow.Top + height - 1); srWindow.Right = (short) (srWindow.Left + width - 1); r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow); if (!r) { int errorCode = Marshal.GetLastWin32Error(); // If we resized the buffer, un-resize it. if (resizeBuffer) { Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, csbi.dwSize); } // Try to give a better error message here Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); if (width > bounds.X) throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.X)); if (height > bounds.Y) throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.Y)); __Error.WinIOError(errorCode, String.Empty); } } public static int LargestWindowWidth { get { // Note this varies based on current screen resolution and // current console font. Do not cache this value. Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); return bounds.X; } } public static int LargestWindowHeight { get { // Note this varies based on current screen resolution and // current console font. Do not cache this value. Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); return bounds.Y; } } public static int WindowLeft { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.srWindow.Left; } set { SetWindowPosition(value, WindowTop); } } public static int WindowTop { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.srWindow.Top; } set { SetWindowPosition(WindowLeft, value); } } public static unsafe void SetWindowPosition(int left, int top) { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); // Get the size of the current console window Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); Win32Native.SMALL_RECT srWindow = csbi.srWindow; // Check for arithmetic underflows & overflows. int newRight = left + srWindow.Right - srWindow.Left + 1; if (left < 0 || newRight > csbi.dwSize.X || newRight < 0) throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos")); int newBottom = top + srWindow.Bottom - srWindow.Top + 1; if (top < 0 || newBottom > csbi.dwSize.Y || newBottom < 0) throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos")); // Preserve the size, but move the position. srWindow.Bottom -= (short) (srWindow.Top - top); srWindow.Right -= (short) (srWindow.Left - left); srWindow.Left = (short) left; srWindow.Top = (short) top; bool r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow); if (!r) __Error.WinIOError(); } public static int CursorLeft { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.dwCursorPosition.X; } set { SetCursorPosition(value, CursorTop); } } public static int CursorTop { get { Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); return csbi.dwCursorPosition.Y; } set { SetCursorPosition(CursorLeft, value); } } public static void SetCursorPosition(int left, int top) { // Note on argument checking - the upper bounds are NOT correct // here! But it looks slightly expensive to compute them. Let // Windows calculate them, then we'll give a nice error message. if (left < 0 || left >= Int16.MaxValue) throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (top < 0 || top >= Int16.MaxValue) throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); IntPtr hConsole = ConsoleOutputHandle; Win32Native.COORD coords = new Win32Native.COORD(); coords.X = (short) left; coords.Y = (short) top; bool r = Win32Native.SetConsoleCursorPosition(hConsole, coords); if (!r) { // Give a nice error message for out of range sizes int errorCode = Marshal.GetLastWin32Error(); Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); if (left < 0 || left >= csbi.dwSize.X) throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); if (top < 0 || top >= csbi.dwSize.Y) throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); __Error.WinIOError(errorCode, String.Empty); } } public static int CursorSize { get { Win32Native.CONSOLE_CURSOR_INFO cci; IntPtr hConsole = ConsoleOutputHandle; bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); if (!r) __Error.WinIOError(); return cci.dwSize; } set { // Value should be a percentage from [1, 100]. if (value < 1 || value > 100) throw new ArgumentOutOfRangeException("value", value, Environment.GetResourceString("ArgumentOutOfRange_CursorSize")); new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); // Win9x: setting the value to 100 doesn't work // correctly, but sets it to 32675. Rounding oddity in OS? if (value == 100 && (Environment.OSInfo & Environment.OSName.Win9x) != 0) value = 99; Win32Native.CONSOLE_CURSOR_INFO cci; IntPtr hConsole = ConsoleOutputHandle; bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); if (!r) __Error.WinIOError(); cci.dwSize = value; r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci); if (!r) __Error.WinIOError(); } } public static bool CursorVisible { get { Win32Native.CONSOLE_CURSOR_INFO cci; IntPtr hConsole = ConsoleOutputHandle; bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); if (!r) __Error.WinIOError(); return cci.bVisible; } set { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); Win32Native.CONSOLE_CURSOR_INFO cci; IntPtr hConsole = ConsoleOutputHandle; bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); if (!r) __Error.WinIOError(); cci.bVisible = value; r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci); if (!r) __Error.WinIOError(); } } public static String Title { [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] get { StringBuilder sb = new StringBuilder(MaxConsoleTitleLength + 1); // As of Windows Server 2003 (and probably all prior // releases), GetConsoleTitle doesn't do anything useful on // empty strings, such as calling SetLastError so callers can // determine whether that 0 was an error or was a success. Win32Native.SetLastError(0); int r = Win32Native.GetConsoleTitle(sb, sb.Capacity); if (r == 0) { // Allow a 0-length title int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0) sb.Length = 0; else __Error.WinIOError(errorCode, String.Empty); } else if (r > MaxConsoleTitleLength) throw new InvalidOperationException(Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong")); return sb.ToString(); } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] set { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); if (value == null) throw new ArgumentNullException("value"); if (value.Length > MaxConsoleTitleLength) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong")); if (!Win32Native.SetConsoleTitle(value)) __Error.WinIOError(); } } [Flags] internal enum ControlKeyState { RightAltPressed = 0x0001, LeftAltPressed = 0x0002, RightCtrlPressed = 0x0004, LeftCtrlPressed = 0x0008, ShiftPressed = 0x0010, NumLockOn = 0x0020, ScrollLockOn = 0x0040, CapsLockOn = 0x0080, EnhancedKey = 0x0100 } [HostProtection(UI=true)] public static ConsoleKeyInfo ReadKey() { return ReadKey(false); } private static bool IsKeyDownEvent(Win32Native.InputRecord ir) { // Check for non-keyboard events & discard them. return (ir.eventType == Win32Native.KEY_EVENT && ir.keyEvent.keyDown); } private static bool IsModKey(short keyCode) { // We should also skip over Shift, Control, and Alt, as well as caps lock. // Apparently we don't need to return ((keyCode >= 0x10 && keyCode <= 0x12) || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91); } [HostProtection(UI=true)] public static ConsoleKeyInfo ReadKey(bool intercept) { Win32Native.InputRecord ir; int numEventsRead = -1; bool r; if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT) { // We had a previous keystroke with repeated characters. ir = _cachedInputRecord; if (_cachedInputRecord.keyEvent.repeatCount == 0) _cachedInputRecord.eventType = -1; else { _cachedInputRecord.keyEvent.repeatCount--; } // We will return one key from this method, so we decrement the // repeatCount here, leaving the cachedInputRecord in the "queue". } else { while (true) { r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead); if (!r || numEventsRead == 0) { // This will fail when stdin is a file (ie, foo < a.txt). // We could theoretically call Console.Read here, but I // think we might do some things incorrectly then. throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleReadKeyOnFile")); } // Skip non key-down events. if (!IsKeyDownEvent(ir)) continue; char ch = ir.keyEvent.uChar; if (ch == 0) { short keyCode = ir.keyEvent.virtualKeyCode; // Skip mod keys. if (IsModKey(keyCode)) continue; } if (ir.keyEvent.repeatCount > 1) { ir.keyEvent.repeatCount--; _cachedInputRecord = ir; //Console.WriteLine("Storing repeated characters from this key event."); } break; } } ControlKeyState state = (ControlKeyState) ir.keyEvent.controlKeyState; bool shift = (state & ControlKeyState.ShiftPressed) != 0; bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0; bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0; ConsoleKeyInfo info = new ConsoleKeyInfo(ir.keyEvent.uChar, (ConsoleKey) ir.keyEvent.virtualKeyCode, shift, alt, control); if (!intercept) Console.Write(ir.keyEvent.uChar); return info; } public static bool KeyAvailable { [HostProtection(UI=true)] get { if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT) return true; Win32Native.InputRecord ir = new Win32Native.InputRecord(); int numEventsRead = 0; while (true) { bool r = Win32Native.PeekConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead); if (!r) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Win32Native.ERROR_INVALID_HANDLE) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleKeyAvailableOnFile")); __Error.WinIOError(errorCode, "stdin"); } if (numEventsRead == 0) return false; short keyCode = ir.keyEvent.virtualKeyCode; // Skip non key-down && mod key events. if (!IsKeyDownEvent(ir) || IsModKey(keyCode)) { r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead); if (!r) __Error.WinIOError(); } else { return true; } } } } public static bool NumberLock { get { short s = Win32Native.GetKeyState(NumberLockVKCode); return (s & 1) == 1; } } public static bool CapsLock { get { short s = Win32Native.GetKeyState(CapsLockVKCode); return (s & 1) == 1; } } public static bool TreatControlCAsInput { [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] get { IntPtr handle = ConsoleInputHandle; if (handle == Win32Native.INVALID_HANDLE_VALUE) throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); int mode = 0; bool r = Win32Native.GetConsoleMode(handle, out mode); if (!r) __Error.WinIOError(); return (mode & Win32Native.ENABLE_PROCESSED_INPUT) == 0; } [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] set { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); IntPtr handle = ConsoleInputHandle; if (handle == Win32Native.INVALID_HANDLE_VALUE) throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); int mode = 0; bool r = Win32Native.GetConsoleMode(handle, out mode); if (value) mode &= ~Win32Native.ENABLE_PROCESSED_INPUT; else mode |= Win32Native.ENABLE_PROCESSED_INPUT; r = Win32Native.SetConsoleMode(handle, mode); if (!r) __Error.WinIOError(); } } #endif // !FEATURE_PAL // During an appdomain unload, we must call into the OS and remove // our delegate from the OS's list of console control handlers. If // we don't do this, the OS will call back on a delegate that no // longer exists. So, subclass CriticalFinalizableObject. // This problem would theoretically exist during process exit for a // single appdomain too, so using a internal sealed class ControlC---- : CriticalFinalizerObject { private bool _hooked; private Win32Native.ConsoleCtrlHandlerRoutine _handler; internal ControlC----() { _handler = new Win32Native.ConsoleCtrlHandlerRoutine(BreakEvent); } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] ~ControlC----() { Unhook(); } [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] internal void Hook() { if (!_hooked) { bool r = Win32Native.SetConsoleCtrlHandler(_handler, true); if (!r) __Error.WinIOError(); _hooked = true; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] internal void Unhook() { if (_hooked) { bool r = Win32Native.SetConsoleCtrlHandler(_handler, false); if (!r) __Error.WinIOError(); _hooked = false; } } } // A class with data so ControlC handlers can be called on a Threadpool thread. private sealed class ControlCDelegateData { internal ConsoleSpecialKey ControlKey; internal bool Cancel; internal bool DelegateStarted; internal ManualResetEvent CompletionEvent; internal ConsoleCancelEventHandler CancelCallbacks; internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks) { this.ControlKey = controlKey; this.CancelCallbacks = cancelCallbacks; this.CompletionEvent = new ManualResetEvent(false); // this.Cancel defaults to false // this.DelegateStarted defaults to false } } // Returns true if we've "handled" the break request, false if // we want to terminate the process (or at least let the next // control handler function have a chance). private static bool BreakEvent(int controlType) { // The thread that this gets called back on has a very small stack on 64 bit systems. There is // not enough space to handle a managed exception being caught and thrown. So, queue up a work // item on another thread for the actual event callback. if (controlType == Win32Native.CTRL_C_EVENT || controlType == Win32Native.CTRL_BREAK_EVENT) { // To avoid race between remove handler and raising the event ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks; if (cancelCallbacks == null) { return false; } // Create the delegate ConsoleSpecialKey controlKey = (controlType == 0) ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak; ControlCDelegateData delegateData = new ControlCDelegateData(controlKey, cancelCallbacks); WaitCallback controlCCallback = new WaitCallback(ControlCDelegate); // Queue the delegate if (!ThreadPool.QueueUserWorkItem(controlCCallback, delegateData)) { BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem returned false without throwing. Unable to execute ControlC handler"); return false; } // Block until the delegate is done. We need to be robust in the face of the work item not executing // but we also want to get control back immediately after it is done and we don't want to give the // handler a fixed time limit in case it needs to display UI. Wait on the event twice, once with a // timout and a second time without if we are sure that the handler actually started. TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30); // 30 seconds delegateData.CompletionEvent.WaitOne(controlCWaitTime, false); if (!delegateData.DelegateStarted) { BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem did not execute the handler within 30 seconds."); return false; } delegateData.CompletionEvent.WaitOne(); delegateData.CompletionEvent.Close(); return delegateData.Cancel; } return false; } // This is the worker delegate that is called on the Threadpool thread to fire the actual events. It must guarentee that it // signals the caller on the ControlC thread so that it does not block indefinitely. private static void ControlCDelegate(object data) { ControlCDelegateData controlCData = (ControlCDelegateData)data; try { controlCData.DelegateStarted = true; ConsoleCancelEventArgs args = new ConsoleCancelEventArgs(controlCData.ControlKey); controlCData.CancelCallbacks(null, args); controlCData.Cancel = args.Cancel; } finally { controlCData.CompletionEvent.Set(); } } // Note: hooking this event allows you to prevent Control-C from // killing a console app, which is somewhat surprising for users. // Some permission seems appropriate. We chose UI permission for lack // of a better one. However, we also applied host protection // permission here as well, for self-affecting process management. // This allows hosts to prevent people from adding a handler for // this event. public static event ConsoleCancelEventHandler CancelKeyPress { [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] add { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); lock(InternalSyncObject) { // Add this delegate to the pile. _cancelCallbacks += value; // If we haven't registered our control-C handler, do it. if (_---- == null) { _---- = new ControlC----(); _----.Hook(); } } } [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] remove { new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); lock(InternalSyncObject) { // If count was 0, call SetConsoleCtrlEvent to remove cb. _cancelCallbacks -= value; BCLDebug.Assert(_cancelCallbacks == null || _cancelCallbacks.GetInvocationList().Length > 0, "Teach Console::CancelKeyPress to handle a non-null but empty list of callbacks"); if (_---- != null && _cancelCallbacks == null) _----.Unhook(); } } } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardError() { return OpenStandardError(_DefaultConsoleBufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardError(int bufferSize) { if (bufferSize < 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); return GetStandardFile(Win32Native.STD_ERROR_HANDLE, FileAccess.Write, bufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardInput() { return OpenStandardInput(_DefaultConsoleBufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardInput(int bufferSize) { if (bufferSize < 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); return GetStandardFile(Win32Native.STD_INPUT_HANDLE, FileAccess.Read, bufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardOutput() { return OpenStandardOutput(_DefaultConsoleBufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] public static Stream OpenStandardOutput(int bufferSize) { if (bufferSize < 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); return GetStandardFile(Win32Native.STD_OUTPUT_HANDLE, FileAccess.Write, bufferSize); } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.AppDomain)] public static void SetIn(TextReader newIn) { if (newIn == null) throw new ArgumentNullException("newIn"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); newIn = TextReader.Synchronized(newIn); lock(InternalSyncObject) { _in = newIn; } } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.AppDomain)] public static void SetOut(TextWriter newOut) { if (newOut == null) throw new ArgumentNullException("newOut"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); _wasOutRedirected = true; newOut = TextWriter.Synchronized(newOut); lock(InternalSyncObject) { _out = newOut; } } [HostProtection(UI=true)] [ResourceExposure(ResourceScope.AppDomain)] public static void SetError(TextWriter newError) { if (newError == null) throw new ArgumentNullException("newError"); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); _wasErrorRedirected = true; newError = TextWriter.Synchronized(newError); lock(InternalSyncObject) { _error = newError; } } [HostProtection(UI=true)] public static int Read() { return In.Read(); } [HostProtection(UI=true)] public static String ReadLine() { return In.ReadLine(); } [HostProtection(UI=true)] public static void WriteLine() { Out.WriteLine(); } [HostProtection(UI=true)] public static void WriteLine(bool value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(char value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(char[] buffer) { Out.WriteLine(buffer); } [HostProtection(UI=true)] public static void WriteLine(char[] buffer, int index, int count) { Out.WriteLine(buffer, index, count); } [HostProtection(UI=true)] public static void WriteLine(decimal value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(double value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(float value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(int value) { Out.WriteLine(value); } [HostProtection(UI=true)] [CLSCompliant(false)] public static void WriteLine(uint value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(long value) { Out.WriteLine(value); } [HostProtection(UI=true)] [CLSCompliant(false)] public static void WriteLine(ulong value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(Object value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(String value) { Out.WriteLine(value); } [HostProtection(UI=true)] public static void WriteLine(String format, Object arg0) { Out.WriteLine(format, arg0); } [HostProtection(UI=true)] public static void WriteLine(String format, Object arg0, Object arg1) { Out.WriteLine(format, arg0, arg1); } [HostProtection(UI=true)] public static void WriteLine(String format, Object arg0, Object arg1, Object arg2) { Out.WriteLine(format, arg0, arg1, arg2); } [HostProtection(UI=true)] [CLSCompliant(false)] public static void WriteLine(String format, Object arg0, Object arg1, Object arg2,Object arg3, __arglist) { Object[] objArgs; int argCount; ArgIterator args = new ArgIterator(__arglist); //+4 to account for the 4 hard-coded arguments at the beginning of the list. argCount = args.GetRemainingCount() + 4; objArgs = new Object[argCount]; //Handle the hard-coded arguments objArgs[0] = arg0; objArgs[1] = arg1; objArgs[2] = arg2; objArgs[3] = arg3; //Walk all of the args in the variable part of the argument list. for (int i=4; i
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- JpegBitmapDecoder.cs
- SimpleModelProvider.cs
- ValueTypeFixupInfo.cs
- EdmProperty.cs
- TextPointer.cs
- UMPAttributes.cs
- Positioning.cs
- ZipIOLocalFileDataDescriptor.cs
- PersonalizationProviderHelper.cs
- MimeWriter.cs
- Line.cs
- SizeKeyFrameCollection.cs
- DataKey.cs
- SiteMap.cs
- Scheduler.cs
- WindowCollection.cs
- RectAnimationUsingKeyFrames.cs
- JsonMessageEncoderFactory.cs
- ConfigPathUtility.cs
- SetterBase.cs
- TemplateInstanceAttribute.cs
- Tile.cs
- DesignerProperties.cs
- HyperLinkField.cs
- DataGridViewDataErrorEventArgs.cs
- PropertyConverter.cs
- TypeSchema.cs
- CapacityStreamGeometryContext.cs
- TextProviderWrapper.cs
- AvTraceDetails.cs
- QueryOptionExpression.cs
- BrushValueSerializer.cs
- DataGridViewRowConverter.cs
- WebPartConnectionsCancelVerb.cs
- PeerInvitationResponse.cs
- QueryAccessibilityHelpEvent.cs
- XamlTypeMapperSchemaContext.cs
- EditingMode.cs
- Message.cs
- SafeMILHandleMemoryPressure.cs
- UserNameSecurityTokenProvider.cs
- DrawItemEvent.cs
- Dynamic.cs
- HttpListenerContext.cs
- ExternalException.cs
- MetadataCollection.cs
- WebBrowser.cs
- SelectionHighlightInfo.cs
- TableItemPattern.cs
- Evidence.cs
- GlyphingCache.cs
- DoubleCollectionConverter.cs
- Models.cs
- TransformerTypeCollection.cs
- documentsequencetextview.cs
- WebScriptMetadataMessageEncoderFactory.cs
- CompositeFontInfo.cs
- XmlDataProvider.cs
- AggregateNode.cs
- ModelPropertyCollectionImpl.cs
- ObjectCloneHelper.cs
- SubpageParagraph.cs
- UInt16.cs
- login.cs
- ChannelDemuxer.cs
- XmlUtil.cs
- ValidationPropertyAttribute.cs
- SmtpReplyReader.cs
- SignatureToken.cs
- MappingException.cs
- HttpPostLocalhostServerProtocol.cs
- SettingsProperty.cs
- SymbolEqualComparer.cs
- TemplateXamlTreeBuilder.cs
- TextTreeFixupNode.cs
- RuntimeWrappedException.cs
- CloudCollection.cs
- ElementAtQueryOperator.cs
- ObjectListItem.cs
- ContentPresenter.cs
- EditableLabelControl.cs
- MembershipValidatePasswordEventArgs.cs
- ImmutableObjectAttribute.cs
- CustomTypeDescriptor.cs
- SHA512Managed.cs
- ExpressionBindingCollection.cs
- CachedTypeface.cs
- base64Transforms.cs
- UriSection.cs
- CodeIdentifiers.cs
- CommaDelimitedStringAttributeCollectionConverter.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- DifferencingCollection.cs
- PolyLineSegment.cs
- ConstraintManager.cs
- BridgeDataRecord.cs
- CopyAction.cs
- DataChangedEventManager.cs
- Int64Converter.cs
- prompt.cs