多次调用 AllocConsole 和 FreeConsole 并在 C# .NET 中保留控制台对象的输入和输出功能
Calling AllocConsole & FreeConsole multiple times and keep In- & Output functionality of Console object in C# .NET
OS: Windows 10 企业版 1703 64 位
我无法在不丢失 windows 表单应用程序中的 Console.ReadKey()
功能的情况下多次分配和释放 控制台 。
此问题与 Exception when using console window in a form application 类似,但 Console.ReadKey()
函数中缺少答案。
以下代码仅适用于第一次执行。收到一个新控制台 window 并且用户必须按任意键。在第二次执行时,文本也会显示,但 Console.ReadKey()
抛出 System.InvalidOperationException
.
System.InvalidOperationException: 'Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.'
为简洁起见,省略了静态 Win32Wrapper class 中的 DllImport 声明。
Win32Wrapper.AllocConsole();
// set standard out handle to console window
var ConOut = Win32Wrapper.CreateFile(
"CONOUT$",
GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
ShareMode.FILE_SHARE_WRITE,
IntPtr.Zero,
CreationDisposition.OPEN_EXISTING,
0,
IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, ConOut);
// set stadard in handle to console window
var ConIn = Win32Wrapper.CreateFile(
"CONIN$",
GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
ShareMode.FILE_SHARE_READ,
IntPtr.Zero,
CreationDisposition.OPEN_EXISTING,
0,
IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, ConIn);
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true });
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
Console.WriteLine("Hello World!"); // works every time
Console.Read(); // works every time
Console.ReadKey(true); // second call: InvalidOperationException
Win32Wrapper.CloseHandle(ConIn)
Win32Wrapper.CloseHandle(ConOut)
return Win32Wrapper.FreeConsole();
我找到了一种模拟上述行为的方法,即不破坏我之前创建的控制台,而是简单地隐藏并再次显示它。
if (FirstTime)
{
FirstTime = false;
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, HWND.Zero);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, HWND.Zero);
Win32Wrapper.AllocConsole(); // show implicitly
}
else
{
Console.Clear(); // clear => simulate new console
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 5); // show (again)
}
Console.WriteLine("Hello World!");
Console.Read();
Console.ReadKey(true);
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 0); // hide
只有第一个函数调用会分配一个新的控制台,以后的调用只会再次显示已经存在的控制台。我只需要一个静态变量来跟踪它。
OS: Windows 10 企业版 1703 64 位
我无法在不丢失 windows 表单应用程序中的 Console.ReadKey()
功能的情况下多次分配和释放 控制台 。
此问题与 Exception when using console window in a form application 类似,但 Console.ReadKey()
函数中缺少答案。
以下代码仅适用于第一次执行。收到一个新控制台 window 并且用户必须按任意键。在第二次执行时,文本也会显示,但 Console.ReadKey()
抛出 System.InvalidOperationException
.
System.InvalidOperationException: 'Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.'
为简洁起见,省略了静态 Win32Wrapper class 中的 DllImport 声明。
Win32Wrapper.AllocConsole();
// set standard out handle to console window
var ConOut = Win32Wrapper.CreateFile(
"CONOUT$",
GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
ShareMode.FILE_SHARE_WRITE,
IntPtr.Zero,
CreationDisposition.OPEN_EXISTING,
0,
IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, ConOut);
// set stadard in handle to console window
var ConIn = Win32Wrapper.CreateFile(
"CONIN$",
GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
ShareMode.FILE_SHARE_READ,
IntPtr.Zero,
CreationDisposition.OPEN_EXISTING,
0,
IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, ConIn);
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true });
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
Console.WriteLine("Hello World!"); // works every time
Console.Read(); // works every time
Console.ReadKey(true); // second call: InvalidOperationException
Win32Wrapper.CloseHandle(ConIn)
Win32Wrapper.CloseHandle(ConOut)
return Win32Wrapper.FreeConsole();
我找到了一种模拟上述行为的方法,即不破坏我之前创建的控制台,而是简单地隐藏并再次显示它。
if (FirstTime)
{
FirstTime = false;
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, HWND.Zero);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, HWND.Zero);
Win32Wrapper.AllocConsole(); // show implicitly
}
else
{
Console.Clear(); // clear => simulate new console
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 5); // show (again)
}
Console.WriteLine("Hello World!");
Console.Read();
Console.ReadKey(true);
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 0); // hide
只有第一个函数调用会分配一个新的控制台,以后的调用只会再次显示已经存在的控制台。我只需要一个静态变量来跟踪它。