调用AllocConsole&;多次使用FreeConsole并保持在-&;C#.NET中Console对象的输出功能

调用AllocConsole&;多次使用FreeConsole并保持在-&;C#.NET中Console对象的输出功能,c#,.net,winapi,console,pinvoke,C#,.net,Winapi,Console,Pinvoke,操作系统:Windows 10 Enterprise 1703 64位 在windows窗体应用程序中,如果不释放控制台.ReadKey()功能,我无法多次分配和释放控制台。 此问题与类似,但在Console.ReadKey()函数中缺少答案 以下代码仅适用于第一次执行。一个接收到一个新的控制台窗口,用户必须按任意键。在第二次执行时,也会显示文本,但Console.ReadKey()会抛出System.InvalidOperationException System.InvalidOperati

操作系统:Windows 10 Enterprise 1703 64位

在windows窗体应用程序中,如果不释放
控制台.ReadKey()
功能,我无法多次分配和释放控制台。 此问题与类似,但在
Console.ReadKey()
函数中缺少答案

以下代码仅适用于第一次执行。一个接收到一个新的控制台窗口,用户必须按任意键。在第二次执行时,也会显示文本,但
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类中的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(第一次)
{
第一次=错误;
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_输出_句柄,HWND.Zero);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_输入_句柄,HWND.Zero);
Win32Wrapper.alloconsole();//隐式显示
}
其他的
{
Console.Clear();//Clear=>模拟新控制台
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(),5);//再次显示
}
控制台。WriteLine(“你好,世界!”);
Console.Read();
Console.ReadKey(true);
Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(),0);//隐藏

只有第一个函数调用会分配一个新的控制台。进一步的调用只会再次显示已经存在的控制台。我只需要一个静态变量来跟踪它。

这是行不通的。将您的程序转换为控制台应用程序。这是不可能的,因为它是GUI应用程序。因此,您可能需要两个不同的可执行文件和一些IPC。您可以标记自己以帮助其他有相同问题的人