Как вывести сообщение в консоль из приложения Windows Forms?

292
23 декабря 2017, 02:51

Приложение может запускаться с параметрами. Есть необходимость вывести хелп с параметрами в этой же консоли, где было запущено приложение, если пользователь ошибся, скажем так. Как при запуске приложения в этой же консоли вывести сообщение?

Answer 1

Проблема в том, что cmd.exe не обрабатывает вывод приложений с графическим интерфейсом. При запуске оболочка проверяет флажок в заголовке исполняемого файла, и если приложение оконное, то оно запускается не блокируя консоль. После этого можно запустить другое приложение, выполнять команды, либо вовсе закрыть окно консоли. Соответственно, если после этого в консоли будут выводиться сообщения, то будет неясно от какого процесса они исходят.

Предлагаю рассмотреть альтернативные варианты:

  1. Выводить сообщение об ошибке в графическом интерфейсе. Раз все приложение оконное, то и сообщение логично показывать в интерфейсе.

  1. С помощью Win32 присоединять консольный вывод к родительскому процессу через AttachConsole и насильно писать в него:

    //импорт функции
    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
    //присоединяемся к родительскому процессу
    AttachConsole(-1)
    //пишем в консоль
    Console.WriteLine("Some message");
    

Это будет выглядеть странно, особенно если в консоли будет запущен другой процесс. Так же если понадобится перенаправление потока вывода, то его придется реализовывать самому.

  1. Сделать приложение консольным (изменить тип вывода в настройках проекта Visual Studio). В этом случае будет работать вывод в консоль. Недостаток в том, что окно консоли появится даже при запуске в проводнике. Консоль можно скрывать с помощью ShowWindow, но полностью избежать его появления не получится.
Answer 2

Как вариант можно создать новую консоль AllocConsole

//импорт функции
[DllImport("kernel32.dll")]
static extern bool AllocConsole();
//....
// Присоиденить консоль
AllocConsole();

и перед выводом её один раз вызвать. Будет создана новая консоль. (Одна консоль на один процесс, т.е. если вызвать из процесса повторно - две не будет).

Если нужно таки писать в родительскую консоль, то можно соиденить AttachConsole и AllocConsole например так

[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll")]
static extern bool AllocConsole();
//
if (!AttachConsole(-1)) AllocConsole (); 

но тогда может возникнуть "конфликт" - два приложения будут писать в одну консоль. Но если обе будут выводить "законченые" (всегда заканчивающиеся переводом каретки, например) и "простые" (без атрибутов цветов очистки экрана и т п) предложения - то возможно не будут мешать друг другу.

READ ALSO
Расположить один объект рядом с другим

Расположить один объект рядом с другим

Необходимо расположить Объект1 рядом с Объект2

274
Отобразить PNG из API во View

Отобразить PNG из API во View

Получаю через API картинку PNG в контроллере

209
Как обработать SqlException - The parametrised query … expects the parameter … which is not supplied

Как обработать SqlException - The parametrised query … expects the parameter … which is not supplied

Имеется форма, на которой расположен DataGridView и к ней BindingNavigator, созданный автоматически

193