C# 如何使用标准输入流而不是Console.ReadKey
如何使用Stream.Read()而不是Console.ReadKey()C# 如何使用标准输入流而不是Console.ReadKey,c#,console,C#,Console,如何使用Stream.Read()而不是Console.ReadKey() while(true) { var c=Console.In.Read(); 控制台写入线(“输入:+c”); } 但该值仅在输入整行时返回 我不想使用Console.ReadKey()来实现这个函数。因为这不利于测试 那么,如何通过流监控用户的密钥输入呢?或通过其他方式。(尽可能不使用接口时).NET Framework和.NET Core使用Win32函数ReadConsoleInput为Console.ReadK
while(true)
{
var c=Console.In.Read();
控制台写入线(“输入:+c”);
}
但该值仅在输入整行时返回
我不想使用Console.ReadKey()来实现这个函数。因为这不利于测试
那么,如何通过流监控用户的密钥输入呢?或通过其他方式。(尽可能不使用接口时).NET Framework和.NET Core使用Win32函数
ReadConsoleInput
为Console.ReadKey()
供电,该函数一次从控制台缓冲区读取一位数据
相反,使用Console.In
或Console.OpenStandardInput()
调用Win32函数GetStdHandle
,然后将句柄包装到私有类\uu ConsoleStream
,该类内部使用ReadFile
或ReadConsole
Win32函数,具体取决于几件事情
默认情况下,控制台流配置有ENABLE_ECHO_INPUT
,它将您键入的每个字符回显到屏幕上。这需要设置启用线路输入
启用线路输入的文档说明:
ReadFile
或ReadConsole
函数仅在读取回车符时返回。如果禁用此模式,则当一个或多个字符可用时,函数返回
因此,如果我们想要一个使用ReadFile
或ReadConsole
的流,我们需要一个禁用这两个标志的控制台句柄。可以这样做:
static class Win32Console
{
public static Stream GetConsoleStreamWithImmediateInput()
{
var handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle.IsInvalid) throw new Win32Exception();
try
{
if (!GetConsoleMode(handle, out var mode)) throw new Win32Exception();
mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(handle, mode)) throw new Win32Exception();
}
catch
{
handle.Close();
throw;
}
return new FileStream(handle, FileAccess.Read);
}
const int STD_INPUT_HANDLE = -10;
const int ENABLE_LINE_INPUT = 0x0002;
const int ENABLE_ECHO_INPUT = 0x0004;
[DllImport("Kernel32.dll", SetLastError = true)]
static extern SafeFileHandle GetStdHandle(int nStdHandle);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetConsoleMode(SafeFileHandle hConsoleHandle, out int mode);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetConsoleMode(SafeFileHandle hConsoleHandle, int mode);
}
这将为您提供一个流,允许您一次读取一个字符,即使尚未输入整行
请注意,这不会将每个字符打印到屏幕上。如果您仍然需要,您必须自己回显它。.NET Framework和.NET Core使用Win32函数ReadConsoleInput
启动Console.ReadKey()
,它一次从控制台缓冲区读取一点数据
相反,使用Console.In
或Console.OpenStandardInput()
调用Win32函数GetStdHandle
,然后将句柄包装到私有类\uu ConsoleStream
,该类内部使用ReadFile
或ReadConsole
Win32函数,具体取决于几件事情
默认情况下,控制台流配置有ENABLE_ECHO_INPUT
,它将您键入的每个字符回显到屏幕上。这需要设置启用线路输入
启用线路输入的文档说明:
ReadFile
或ReadConsole
函数仅在读取回车符时返回。如果禁用此模式,则当一个或多个字符可用时,函数返回
因此,如果我们想要一个使用ReadFile
或ReadConsole
的流,我们需要一个禁用这两个标志的控制台句柄。可以这样做:
static class Win32Console
{
public static Stream GetConsoleStreamWithImmediateInput()
{
var handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle.IsInvalid) throw new Win32Exception();
try
{
if (!GetConsoleMode(handle, out var mode)) throw new Win32Exception();
mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(handle, mode)) throw new Win32Exception();
}
catch
{
handle.Close();
throw;
}
return new FileStream(handle, FileAccess.Read);
}
const int STD_INPUT_HANDLE = -10;
const int ENABLE_LINE_INPUT = 0x0002;
const int ENABLE_ECHO_INPUT = 0x0004;
[DllImport("Kernel32.dll", SetLastError = true)]
static extern SafeFileHandle GetStdHandle(int nStdHandle);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetConsoleMode(SafeFileHandle hConsoleHandle, out int mode);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetConsoleMode(SafeFileHandle hConsoleHandle, int mode);
}
这将为您提供一个流,允许您一次读取一个字符,即使尚未输入整行
请注意,这不会将每个字符打印到屏幕上。如果您仍然希望这样做,您必须自己回显它。我想问的是,它可能无法在某些用户的计算机上工作,因为我无法保证对控制台应用程序运行的环境进行精确控制。请尝试。不过,这些都是自Windows 2000以来的标准Windows功能,因此我不希望出现任何奇怪的不兼容。我想问的是,它可能无法在某些用户的计算机上工作,因为我无法保证对控制台应用程序运行的环境进行精确控制。请尝试。不过,这些都是自Windows 2000以来的标准Windows函数,所以我不希望出现任何奇怪的不兼容。