Ответ 1
Microsoft разработала консольные и графические приложения, которые будут взаимоисключающими. Этот бит близорукости означает, что идеального решения нет. Наиболее популярный подход состоит в том, чтобы иметь два исполняемых файла (например, cscript/wscript, java/javaw, devenv.com/devenv.exe и т.д.), однако вы указали, что считаете это "обманом".
У вас есть два варианта: создать "исполняемый файл консоли" или "исполняемый файл gui", а затем используйте код, чтобы попытаться обеспечить другое поведение.
- Исполняемый файл 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);
}
Я скомпилировал его с cygwin gcc - YMMV с MSVC.
Вторая проблема заключается в том, что при запуске из проводника ваша программа будет на долю секунды отобразите консольное окно. Там нет программного пути, потому что консоль созданный Windows при запуске приложения до его запуска. Единственное, что вы можете сделать это, в вашем установщике, сделать ярлык для вашей программы с помощью команды show SW_HIDE (т.е. 0). Это повлияет только на консоль, если вы не намеренно почитаете поле wShowWindow для STARTUPINFO в вашей программе, поэтому не делайте этого.
Я протестировал это, взломав cygwin "mkshortcut.exe". Как вы достигаете это в вашей программе установки по вашему выбору.
Пользователь все равно может запустить вашу программу, найдя исполняемый файл в проводнике и дважды щелкнув по нему, минуя ярлык сокрытия консоли и увидев красную черную вспышку консольного окна. Вы ничего не можете с этим поделать.