Может ли консольное приложение Win32 определить, запущено ли оно из проводника или нет? - PullRequest
35 голосов
/ 04 февраля 2009

Мне нужно создать консольное приложение, которому нужны определенные параметры. Если они отсутствуют или неправильные, я распечатываю сообщение об ошибке.

Теперь проблема: если кто-то запускает программу из проводника, дважды щелкнув окно консоли, сразу исчезает. (Но приложение не совсем бесполезно из проводника, вы можете перетащить на него файлы, и оно будет работать)

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

Есть ли способ отличить эти ситуации?

Ответы [ 5 ]

29 голосов
/ 05 февраля 2009

См. http://support.microsoft.com/kb/99115, «ИНФОРМАЦИЯ: Предотвращение исчезновения окна консоли».

Идея состоит в том, чтобы использовать GetConsoleScreenBufferInfo, чтобы определить, что курсор не переместился из начальной позиции 0,0.

Пример кода из @tomlogic, основанный на ссылочной статье базы знаний:

// call in main() before printing to stdout
// returns TRUE if program is in its own console (cursor at 0,0) or
// FALSE if it was launched from an existing console.
// See http://support.microsoft.com/kb/99115
#include <stdio.h>
#include <windows.h>
int separate_console( void)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;

    if (!GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE), &csbi))
    {
        printf( "GetConsoleScreenBufferInfo failed: %lu\n", GetLastError());
        return FALSE;
    }

    // if cursor position is (0,0) then we were launched in a separate console
    return ((!csbi.dwCursorPosition.X) && (!csbi.dwCursorPosition.Y));
}
5 голосов
/ 10 августа 2010

GetConsoleTitle()

Я видел код, который выполняет

if (!GetConsoleTitle(NULL, 0) && GetLastError() == ERROR_SUCCESS) {
    // Console
} else {
    // GUI
}

НО ... Я обнаружил, что AttachConsole() более полезен

В C ++ (вне головы, я не программист C ++)

if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
    // GUI
} else {
    // Console, and you have a handle to the console that already exists.
}

Более эффективен. Кроме того, если вы попали в среду с графическим интерфейсом и хотели бы оставаться там как можно дольше, но позже обнаружите что-то катастрофическое, что действительно может использовать дамп в окне консоли (вы не можете быть выписаны, написав поле редактирования окно, чтобы привязать его к системному журналу NT или присоединить к нему и выбросить MessageBox()), а затем вы сможете AllocConsole() позже в процессе, когда методы GUI потерпели неудачу.

3 голосов
/ 04 февраля 2009

Полагаю, cmd.exe устанавливает переменные окружения CMDCMDLINE и CMDEXTVERSION при запуске. Поэтому, если они установлены, ваша программа, скорее всего, была запущена из оболочки.

Это не надежно, но это что-то.

Также возможно определить PID вашего родителя несколькими запутанными и, возможно, ненадежными способами, или я так понял. Вы можете посмотреть на это.

0 голосов
/ 10 июля 2014

Это работает как шарм:

@echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" goto nonconsole

:console
<do something>
goto exit

:nonconsole
<do something>
pause

:exit

Скопировано из этой темы . Я также попытался оценить% cmdcmdline% самостоятельно, однако есть проблема с символами кавычек ("), которая не позволяет что-то вроде , если"% cmdcmdline% "=="% ComSpec% "goto [target] не работает.

0 голосов
/ 04 февраля 2009

Как насчет ожидания нажатия клавиши при отображении сообщения об ошибке, а не в другое время?

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