Различают, запускается ли программа нажатием на значок, вводом его имени в консоли или из командного файла - PullRequest
4 голосов
/ 23 декабря 2011

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

Я спрашиваю об этом, потому что я пытаюсь реализовать интеллектуальное "press enter to exit" сообщение, которое будет работать толькоесли консольная программа вызывается нажатием на ее значок в проводнике.Без этого результатом является то, что программа мигает только в течение доли секунды, но если программа запускается из контекста уже открытой консоли, то это становится раздражающим.Аналогичная ситуация возникает, когда программа запускается внутри файла bat или cmd, поэтому приостановка в конце также нежелательна, поскольку в файлах bat есть команда 'pause', которая должна это делать.


Итак, у нас есть 2Режимы:

  • программа сообщает "press enter to exit" при запуске:
    • прямой щелчок в проводнике
    • нажатие на ярлык
  • Просто выйдите, когда:
    • его имя набрано в консоли
    • оно запускается из файла bat / cmd
    • оно запускается из другого консольного приложения

Ответы [ 4 ]

5 голосов
/ 23 декабря 2011

Использование Windows API:

Вы можете использовать функцию API GetConsoleProcessList (доступна только в Windows XP / 2003 и выше ). Возвращает список процессов, которые подключены к текущей консоли. Когда ваша программа запускается в режиме «без консоли», она является единственным процессом, подключенным к текущей консоли. Когда ваша программа запускается из другого процесса, который уже имеет консоль, к текущей консоли будет подключено более одного процесса.

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

Пример программы (я использовал Visual C ++ с шаблоном консольного приложения):

#include "stdafx.h"
#include <iostream>
#include <Windows.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD procIDs[2];
    DWORD maxCount = 2;
    DWORD result = GetConsoleProcessList((LPDWORD)procIDs, maxCount);
    cout << "Number of processes listed: " << result << endl;
    if (result == 1)
    {
        system("pause");
    }
    return 0;
}

Нам нужно только перечислить до 2 процессов, потому что нам важно только, есть ли 1 или more than 1.


Использование API-интерфейсов Windows, присутствующих в Windows 2000:

GetConsoleWindow возвращает дескриптор окна консоли, связанной с текущим процессом (если есть). GetWindowThreadProcessId может сказать вам, какой процесс создал окно. И наконец, GetCurrentProcessId сообщает вам идентификатор текущего процесса. На основании этой информации вы можете сделать несколько полезных выводов:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    HWND consoleWindow = GetConsoleWindow();
    if (consoleWindow != NULL)
    {
        DWORD windowCreatorProcessId;
        GetWindowThreadProcessId(consoleWindow, &windowCreatorProcessId);
        if (windowCreatorProcessId == GetCurrentProcessId())
        {
            cout << "Console window was created by this process." << endl;
            system("pause");
        }
        else
            cout << "Console window was not created by this process." << endl;
    }
    else
        cout << "No console window is associated with this process." << endl;
    return 0;
}

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

2 голосов
/ 23 декабря 2011

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

//Pseudo-code!!

int main(int argc, char** argv) {
    //...
    if(argv[1] == SHOULD_PAUSE) system("pause");
    return 0;
}
0 голосов
/ 23 декабря 2011

Разрабатывая мой комментарий, вместо того, чтобы пытаться рассказать, как выполнялась программа (что я даже не знаю, возможно, я бы предположил, что нет никакой разницы / различий вообще), я бы реализовал подобное функциональность любым из двух способов:

  • Добавить дополнительный аргумент в программу, который либо заставит ее «остановиться» в конце перед завершением, либо нет. то есть. У вас может быть что-то вроде -w, чтобы заставить его ждать, или -W, чтобы заставить его не ждать, а по умолчанию не ждать (или наоборот). Вы можете добавить аргументы через ярлыки.

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

0 голосов
/ 23 декабря 2011

Есть простой способ сделать это, и, конечно, более сложный способ. В конце концов, более сложный способ может быть веселее, но, вероятно, доставит больше хлопот, чем стоит.

Для простого способа добавьте в программу аргумент командной строки, --pause-on-exit или что-то подобное. Передайте дополнительный аргумент при вызове его из пакетного файла или значка запуска. Конечно, вы могли бы проверить переменную окружения на похожий эффект.

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

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