Вызов Console.WriteLine перед выделением консоли

Недавно я столкнулся со следующей проблемой в своем приложении: оно не показывало никакого вывода на консоль, хотя консоль была выделена с помощью AllocConsole. Вскоре мне удалось выяснить, что это было вызвано попыткой (спрятанной глубоко в коде) записать в консоль до вызова AllocConsole. Так это выглядело так:

Console.WriteLine("Foo"); // no console allocated yet
AllocConsole();           // console window appears
Console.WriteLine("Bar"); // expecting "Bar" in the console, but the console is blank

Итак, мой вопрос: почему это происходит? Я не вижу никаких исключений (хотя полагаю, что они есть).


person Dmitrii Erokhin    schedule 24.09.2011    source источник
comment
Теперь, когда объяснено, почему это произошло, я надеюсь, кто-нибудь объяснит, что с этим делать. Разве не используется любая сторонняя библиотека, которая может писать в консоль и портить все остальное? Является ли правильным решением только принять решение заранее и AllocConsole прежде чем делать что-либо еще?   -  person Miserable Variable    schedule 24.09.2011
comment
@Hemal Я использовал подход, описанный Риком, - вызов Console.OpenStandartOutput() после AllocConsole. Таким образом, я могу быть уверен, что по крайней мере весь вывод, написанный после AllocConsole, будет показан.   -  person Dmitrii Erokhin    schedule 24.09.2011


Ответы (3)


При первом использовании Console.WriteLine класс Console создает TextWriter и связывает его со свойством Console.Out. Это делается с помощью Win32, чтобы открыть низкоуровневый дескриптор файла, связанный с дескриптором файла стандартного вывода. Если стандартный дескриптор вывода недействителен, для Console.Out устанавливается значение TextWriter.Null, который отбрасывает весь вывод.

Функция Win32 AllocConsole создает и устанавливает стандартный дескриптор вывода, поэтому после ее вызова стандартный дескриптор вывода либо отличается, либо теперь действителен. В любом случае Console.Out уже настроено либо на использование старого стандартного вывода, либо на отбрасывание всего вывода.

Чтобы принудительно повторно открыть Console.Out после вызова AllocConsole, вы можете использовать этот метод:

person Rick Sladkey    schedule 24.09.2011
comment
Ух ты. На случай, если кто-то еще увидит это, похоже, это может произойти, как будто это состояние гонки - Alloc, затем напишите в консоль и ничего не получите. Кроме того, мне пришлось написать Console.SetOut(new StreamWriter(Console.OpenStandardOutput()); Вызов Console.OpenStandardOutput() сам по себе не помог. - person MatthewMartin; 18.04.2013

Вероятно, потому что статический конструктор класса Console настраивает поток вывода при первом вызове Console.WriteLine. Поскольку нет подключенной консоли и, следовательно, нет стандартного дескриптора вывода, вывод направляется в битовое ведро. И когда вы вызываете AllocConsole позже, ничто в классе Console не уведомляется о том, что консоль теперь существует. У него нет возможности прикрепить Console.Out к вновь созданному стандартному дескриптору вывода.

person Jim Mischel    schedule 24.09.2011

Процесс может быть связан только с одним console, поэтому AllocConsole function завершается ошибкой, если вызывающий процесс уже имеет console. А в приложении console уже есть console. Подробнее см. здесь

person Ujjwal Manandhar    schedule 24.09.2011
comment
Мое приложение скомпилировано как приложение с графическим интерфейсом, но оно использует консоль при запуске с параметрами командной строки. - person Dmitrii Erokhin; 24.09.2011
comment
Откуда вы знаете, что это консольное приложение? Это вполне может быть приложение Windows с консолью. Редактировать: сказал вам. - person BoltClock; 24.09.2011
comment
Console.WriteLine был написан над AllocConsole, поэтому я так и думал. в любом случае я извиняюсь за это :) GetLastError() может вам что-то сказать в этом случае - person Ujjwal Manandhar; 24.09.2011