Приложение для Windows, которое по желанию остается подключенным к консоли - PullRequest
2 голосов
/ 07 ноября 2011

У меня есть приложение Windows (написано на C, скомпилировано с MSVC Express Edition, 32-битный режим), которое имеет два основных режима работы:

  • Оконный режим - создайте окно и нарисуйте в нем вещи (а именно, фрактал).
  • Режим эталонного теста - при запуске с --benchmark в качестве аргумента не создавать окно, а просто выводить некоторую статистику эталонного теста в стандартный вывод.

Во время разработки я скомпилировал как консольное приложение и использовал SDL для создания окна и выполнения других функций графического интерфейса. Таким образом, режим бенчмарка работает нормально (окно не создается), а в графическом режиме просто есть длительное окно консоли.

Однако для моей компиляции релиза я включил подсистему Windows вместо Console. (Как объяснено в этот вопрос ). Это прекрасно работает, за исключением того, что я вдруг обнаружил, что больше не могу запускать тесты. : О

Мне просто интересно, есть ли способ для приложения выбрать во время выполнения (например, на основании заданной командной строки), какой тип поведения подсистемы использовать?

Я провел некоторые эксперименты с файлами EXE в Windows (проводник, блокнот, winword), и ни один из них, похоже, ничего не выводил на консоль при запуске с аргументом, подобным "/?" (который поддерживает большинство консольных приложений Windows). Так что это не похоже на это, но я подумал, что стоит спросить здесь, если есть особый трюк.

Обновление. Похоже, нет, вы не можете. Спасибо за ответы, ребята.

Дополнительный академический вопрос. Означает ли это, что выбор подсистемы отмечен в заголовке EXE, и именно операционная система проверяет это и настраивает окно или подключает его к консоли, из которой запускается? Я не знаю много о загрузке EXE, но мне было бы интересно узнать несколько деталей здесь.

Заключение. Я думаю, что есть четыре хороших решения (плюс два полу-решения, всего пять: p) на выбор:

  1. Используйте консольную подсистему, но используйте FreeConsole при работе в режиме графического интерфейса.
  2. Используйте систему Windows и AllocConsole при работе в режиме тестирования. Не идеально, если fractal.exe запускается с существующей консоли, поэтому я считаю это половиной решения; -).
  3. Просто используйте один исполняемый файл для каждой подсистемы, fractal.exe и fractalgui.exe.
  4. Иметь два (или более) исполняемых файла, один из которых выполняет свою работу и передает ее другому, чтобы отобразить его на консоли или в соответствующем окне. Нужно немного подумать о том, как разделить программы и как общаться между ними.
  5. Еще одно половинное решение: пусть fractalgui.exe распечатает эталонный эталонный тест и передаст его утилите, которая просто распечатает его.

Я еще не выбрал, но я склоняюсь к # 3.

Спасибо Маттео и Смерлину за идеи!

Ответы [ 3 ]

2 голосов
/ 07 ноября 2011

Чтобы добавить ответ @ smerlin, другой часто встречающийся метод (цитируемый в статьях, на которые я ссылался внутри комментария) - пометить ваше приложение как консольное, но освободить консоль (используя FreeConsole), когда вы определитечто вам это не нужно.

Вот как ildasm делает это, но у него есть недостаток - мигать консоль на короткое время между запуском приложения и вызовом FreeConsole.

Дополнительный академический вопрос .Означает ли это, что выбор подсистемы отмечен в заголовке EXE, и именно операционная система проверяет это и настраивает окно или подключает его к консоли, из которой запускается?Я не очень разбираюсь в загрузке EXE, но мне было бы интересно узнать некоторые подробности здесь.

Да, загрузчик проверяет PE-заголовок и настраивает все в соответствии с подсистемой, указанной здесь.

Контрастность с подходом * NIX: ни один исполняемый файл не является "особенным", и у всех есть работающий stdin / stdout / stderr;приложения, которые хотят что-то отобразить, будут вызывать соответствующие функции Xlib.Недостаток заключается в том, что приложения с графическим интерфейсом не имеют никакого понятия, если приложение, которое вы запускаете, обычно использует консоль, поэтому система должна спросить, хотите ли вы также создать эмулятор терминала или отказаться от стандартных потоков и просто подождать, пока оно создаст окно.(очевидно, ярлыки хранят эту информацию).

2 голосов
/ 07 ноября 2011

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

Тогда общее решение этой проблемы - иметь консольное приложение, которое при необходимости запускает ваше графическое приложение

Для вашего теста производительности он просто напечатает вашу статистику.

пример настройки:
- fractalgui.exe (подсистема: windows)
- fractal.exe (подсистема: консоль)

* ярлык на рабочем столе пользователя ссылается на ваш fractalgui.exe
* если пользователь запускает fractal.exe с консоли, fractal exe запускает fractalgui.exe
* если пользователь запускает fractal.exe --benchmark, он либо сам выполняет тест (если возможно добавить эту логику тестирования в другой исполняемый файл) и печатает информацию непосредственно в консоль, либо - если это невозможно - ему нужно запустить fractalgui.exe --nogui --benchmark. Сложный случай - получить вывод от fractalgui.exe к fractal.exe, чтобы вы могли распечатать его на соответствующей консоли. Есть несколько способов сделать это, например, именованные каналы (есть способы запустить fractalgui.exe таким образом, что вы можете просто использовать там stdout / cout, и данные будут переданы на стандартный вывод fractal.exe, но я не помню, как именно это работает больше (править : возможно это работает)). Самый простой способ - запустить fractalgui.exe --nogui --benchmark > mylogfile, а затем распечатать файл mylogfile после завершения fractalgui.exe (поскольку stdout / cout для fractalgui.exe будет работать, если вывод перенаправлен в файл), однако вы не получите «живой» вывод, так как все результаты будут напечатаны на консоли, когда fractalgui.exe уже завершен.

0 голосов
/ 18 ноября 2011

Я описал метод достижения этого в мой вопрос здесь .

Маттео уже упомянул трюк .com, но это только часть жизнеспособного решения.

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