/* #region Standard streams * // Important note: I manage the streams, but I don't write to or * // read from them. * // To write to the console: * // JConsole.Out.Write() * // JConsole.Error.Write() * // To read from the console: * // JConsole.In.Read() * * // TODO: Other stream types * // I'd really like to support other than FileStream. NetworkStream, for example, * // could be really cool. The problem is that the Stream class doesn't have a * // Handle property, so there's no way that I could reliably redirect the I/O. * // I guess I could write it so that it could identify FileStream and NetworkStream. * // If it sees either of those, then it calls SetStdHandle and does all that. * // Otherwise it just goes about its merry way, ignoring SetStdHandle. * // * // This isn't a problem for the .NET 1.1 or 2.0 Console class because it probably * // doesn't worry about sharing. * * // TODO: Sharing * // The Windows Console API allows sharing the console among processes. * // Many different processes can be talking to a single console, * // and apparently any of those processes can change the input, output, or error handles * // at any time. * // * // As currently written, this does not allow for that. Another process changing the * // handle will not affect the program that's using this class. * // * // I could check the STDIN handle every time it's accessed, to ensure that * // it hasn't been changed by another process. If it's been changed, I abandon * // the current stream and open a new one. * // * // I can't Close() the current stream because I don't know if other parts of the * // program are using it. * // * // One problem: programs that assign a variable to JConsole.In will then be * // writing to the wrong file. Do I just document that and go on? * // I think so. People who will use this class will have to understand that * // the rug can be pulled out from underneath them at any time. * // * // Another solution would be to create ConsoleInputStream and ConsoleOutputStream * // classes that allow the underlying file to change. I resist that because * // then I wouldn't be able to use FileStream descendants. * // * private static FileStream stdIn = null; * private static FileStream stdOut = null; * private static FileStream stdErr = null; * * private static StreamReader inputReader = null; * private static StreamWriter outputWriter = null; * private static StreamWriter errorWriter = null; * * private static bool ownsInput = false; * private static bool ownsOutput = false; * private static bool ownsError = false; * * public static StreamReader In * { * get * { * if (stdIn == null) * { * IntPtr handle = WinCon.GetStdHandle(WinCon.STD_INPUT_HANDLE); * if (handle.ToInt32() == WinApi.INVALID_HANDLE_VALUE) * { * throw new IOException("Unable to get standard input handle", Marshal.GetLastWin32Error()); * } * stdIn = new FileStream(handle, FileAccess.ReadWrite, false); * inputReader = new StreamReader(stdIn); * ownsInput = true; * } * return inputReader; * } * } * * public static void SetIn(FileStream aStream) * { * if (!WinCon.SetStdHandle(WinCon.STD_INPUT_HANDLE, aStream.Handle)) * { * throw new IOException("Unable to set standard input handle", Marshal.GetLastWin32Error()); * } * if (inputReader != null) * { * inputReader.Close(); * } * if (ownsInput && stdIn != null) * { * stdIn.Close(); * } * stdIn = aStream; * inputReader = new StreamReader(stdIn); * ownsInput = false; * } * * public static void SetIn(string Filename) * { * SetIn(new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); * ownsInput = true; * } * * private static StreamWriter CreateWriter(FileStream fs) * { * StreamWriter sw = new StreamWriter(fs); * sw.AutoFlush = true; * return sw; * } * * public static StreamWriter Out * { * get * { * if (stdOut == null) * { * Console.Out.Close(); * IntPtr handle = WinCon.GetStdHandle(WinCon.STD_OUTPUT_HANDLE); * if (handle.ToInt32() == WinApi.INVALID_HANDLE_VALUE) * { * throw new IOException("Unable to get standard output handle", Marshal.GetLastWin32Error()); * } * stdOut = new FileStream(handle, FileAccess.Write, false); * outputWriter = CreateWriter(stdOut); * ownsOutput = true; * } * return outputWriter; * } * } * * public static void SetOut(FileStream aStream) * { * if (!WinCon.SetStdHandle(WinCon.STD_OUTPUT_HANDLE, aStream.Handle)) * { * throw new IOException("Unable to set standard output handle", Marshal.GetLastWin32Error()); * } * if (outputWriter != null) * { * outputWriter.Close(); * } * if (ownsOutput && stdOut != null) * { * stdOut.Close(); * } * stdOut = aStream; * outputWriter = CreateWriter(stdOut); * ownsOutput = false; * } * * public static void SetOut(string Filename) * { * SetOut(new FileStream(Filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)); * ownsOutput = true; * } * * public static StreamWriter Error * { * get * { * if (stdErr == null) * { * IntPtr handle = WinCon.GetStdHandle(WinCon.STD_ERROR_HANDLE); * if (handle.ToInt32() == WinApi.INVALID_HANDLE_VALUE) * { * throw new IOException("Unable to get standard error handle", Marshal.GetLastWin32Error()); * } * stdErr = new FileStream(handle, FileAccess.Write, false); * errorWriter = CreateWriter(stdErr); * ownsError = true; * } * return errorWriter; * } * } * * public static void SetError(FileStream aStream) * { * if (!WinCon.SetStdHandle(WinCon.STD_ERROR_HANDLE, aStream.Handle)) * { * throw new IOException("Unable to set standard error handle", Marshal.GetLastWin32Error()); * } * if (errorWriter != null) * { * errorWriter.Close(); * } * if (ownsError && stdErr != null) * { * stdErr.Close(); * } * stdErr = aStream; * errorWriter = CreateWriter(stdErr); * ownsError = false; * } * * public static void SetError(string Filename) * { * SetError(new FileStream(Filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)); * ownsError = true; * } * #endregion */ public static void GenerateCtrlEventType(ConsoleControlEventType eventId, int processGroupId) { if (!WinCon.GenerateConsoleCtrlEvent((int)eventId, processGroupId)) { throw new IOException("Error generating event.", Marshal.GetLastWin32Error()); } }
// Console control event handler raises the ConsoleControlEvent. // This method is called by the console API when a control event occurs. private static bool ControlHandler(ConsoleControlEventType ctrlType) { switch (ctrlType) { case ConsoleControlEventType.CtrlC: case ConsoleControlEventType.CtrlBreak: case ConsoleControlEventType.CtrlClose: case ConsoleControlEventType.CtrlLogoff: case ConsoleControlEventType.CtrlShutdown: if (ControlEvent != null) { ConsoleControlEventArgs e = new ConsoleControlEventArgs(ctrlType); ControlEvent(null, e); return(e.Cancel); } break; } return(false); }
// Console control event handler raises the ConsoleControlEvent. // This method is called by the console API when a control event occurs. private static bool ControlHandler(ConsoleControlEventType ctrlType) { switch (ctrlType) { case ConsoleControlEventType.CtrlC: case ConsoleControlEventType.CtrlBreak: case ConsoleControlEventType.CtrlClose: case ConsoleControlEventType.CtrlLogoff: case ConsoleControlEventType.CtrlShutdown: if (ControlEvent != null) { ConsoleControlEventArgs e = new ConsoleControlEventArgs(ctrlType); ControlEvent(null, e); return e.Cancel; } break; } return false; }
/// <summary> /// Creates a new instance of the ConsoleControlEventArgs class. /// </summary> /// <param name="evType">Type of control event.</param> public ConsoleControlEventArgs(ConsoleControlEventType evType) { this.evType = evType; }
/// <summary> /// Generate a console control event. /// </summary> /// <param name="eventId">The event to generate. This must be CtrlC or CtrlBreak.</param> /// <param name="processGroupId">In most cases, set to 0 to send the event to /// all attached processes.</param> public static void GenerateCtrlEvent(ConsoleControlEventType eventId, int processGroupId) { if (!WinCon.GenerateConsoleCtrlEvent((int)eventId, processGroupId)) { throw new IOException("Error generating event.", Marshal.GetLastWin32Error()); } }