Многократный вызов AllocConsole & FreeConsole и сохранение функциональности In-Output объекта Console в C # .NET - PullRequest
0 голосов
/ 18 октября 2019

ОС: Windows 10 Enterprise 1703 64-разрядная

Я не могу выделить и освободить консоль более одного раза без потери функциональности Console.ReadKey() в WindowsФорма заявки. Этот вопрос похож на Исключение при использовании окна консоли в приложении формы , но в функции 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.'

Для краткости опущены объявления DllImport в статическом классе Win32Wrapper.

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();

1 Ответ

0 голосов
/ 18 октября 2019

Я нашел способ смоделировать вышеупомянутое поведение, не разрушая созданную ранее консоль, а просто просто скрывая и отображая ее снова.

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

Только первый вызов функции выделяет новую консоль, дальнейшие вызовы толькопокажите уже существующую консоль снова. Все, что мне нужно, это статическая переменная, чтобы отследить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...