Microsoft разработала консольные и графические приложения, чтобы быть взаимоисключающими.
Этот бит близорукости означает, что не существует идеального решения.
Самый популярный подход - иметь два исполняемых файла (например, cscript / wscript,
java / javaw, devenv.com / devenv.exe и т. д.), однако вы указали, что считаете это «изменой».
У вас есть два варианта - сделать «исполняемый файл консоли» или «исполняемый файл gui»,
а затем используйте код, чтобы попытаться обеспечить другое поведение.
cmd.exe
будет предполагать, что ваша программа не поддерживает консольный ввод-вывод, поэтому не будет ждать ее завершения
перед продолжением, что в интерактивном режиме (т.е. не в пакетном режиме) означает отображение следующего ("C:\>
") приглашения
и чтение с клавиатуры. Так что даже если вы используете AttachConsole, ваш вывод будет смешанным
с выводом cmd
, и ситуация ухудшается, если вы попытаетесь сделать ввод. Это в основном не стартер.
- Исполняемый файл консоли:
Вопреки распространенному мнению, ничто не мешает отображению графического интерфейса исполняемого файла консоли, но есть две проблемы.
Во-первых, если вы запустите его из командной строки без аргументов (вам нужен графический интерфейс),
cmd
все еще будет ждать его завершения, прежде чем продолжить, так что
Консоль будет непригодна для использования в течение всего времени. Это можно преодолеть, запустив
второй процесс того же исполняемого файла (вы считаете это мошенничеством?),
передача флага DETACHED_PROCESS в CreateProcess () и немедленный выход.
Новый процесс может обнаружить, что у него нет консоли, и отобразить графический интерфейс.
Вот код C, иллюстрирующий этот подход:
#include <stdio.h>
#include <windows.h>
int main(int argc, char *argv[])
{
if (GetStdHandle(STD_OUTPUT_HANDLE) == 0) // no console, we must be the child process
{
MessageBox(0, "Hello GUI world!", "", 0);
}
else if (argc > 1) // we have command line args
{
printf("Hello console world!\n");
}
else // no command line args but a console - launch child process
{
DWORD dwCreationFlags = CREATE_DEFAULT_ERROR_MODE | DETACHED_PROCESS;
STARTUPINFO startinfo;
PROCESS_INFORMATION procinfo;
ZeroMemory(&startinfo, sizeof(startinfo));
startinfo.cb = sizeof(startinfo);
if (!CreateProcess(NULL, argv[0], NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &startinfo, &procinfo))
MessageBox(0, "CreateProcess() failed :(", "", 0);
}
exit(0);
}
Я скомпилировал его с помощью gg cygwin - YMMV с MSVC.
Вторая проблема заключается в том, что при запуске из Проводника ваша программа будет работать в течение доли секунды.
отобразить окно консоли. Там нет никакого программного способа обойти это, потому что консоль
создается Windows при запуске приложения до его запуска. Единственное, что вы можете
do в вашей программе установки создайте ярлык для вашей программы с помощью команды "show command"
SW_HIDE (т.е. 0). Это повлияет только на консоль, если вы сознательно не соблюдаете поле wShowWindow в STARTUPINFO
в вашей программе, так что не делайте этого.
Я проверил это, взломав cygwin "mkshortcut.exe". Как вы делаете
это в вашей программе установки по вашему выбору.
Пользователь по-прежнему может, конечно, запустить вашу программу, найдя исполняемый файл в Проводнике и
дважды щелкнув по нему, минуя скрывающий консоль ярлык и увидев короткую черную вспышку окна консоли. С этим ничего не поделаешь.