Как узнать, есть ли у окна, созданного с помощью ShellExecuteEx, процесс?

Я использую ShellExecuteEx запустить внешнее приложение:

SHELLEXECUTEINFO shExInfo = { 0 };
    shExInfo.cbSize = sizeof(shExInfo);
    shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    shExInfo.hwnd = 0;
    shExInfo.lpVerb = L"runas";                // Operation to perform
    shExInfo.lpFile = windowStringContainingAppPath.c_str();       // Application to start    
    shExInfo.lpParameters = windowStringContainingAppParameters.c_str();                  // Additional parameters
    shExInfo.lpDirectory = 0;
    shExInfo.nShow = SW_SHOW;
    shExInfo.hInstApp = 0;

    if(ShellExecuteEx(&shExInfo))
    {
        WaitForSingleObject(shExInfo.hProcess, INFINITE);

        DeleteFile(wsMesh3dx64Parameter.c_str());

        CloseHandle(shExInfo.hProcess);
    }

Все работает отлично, но существует незапланированное поведение этого внешнего приложения, которое после закрытия главного окна его процесс все еще активен. Это мешает WaitForSingleObject(shExInfo.hProcess, INFINITE); от возвращения, и я должен прекратить процесс вручную.

Вместо этого я ищу способ заменить WaitForSingleObject(shExInfo.hProcess, INFINITE);с циклом, который проверяет, принадлежит ли внешнему процессу окно и, если нет, закрывает его.

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

ОБНОВИТЬ:

Благодаря ответу Робсона мне удалось сделать то, что я намеревался:

struct Porcess_ID_HWND
{
    DWORD processID;
    HWND processhWnd;
};

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    Porcess_ID_HWND*info = (Porcess_ID_HWND*)lParam;

    DWORD processID;
    GetWindowThreadProcessId(hWnd, &processID);

    if (processID == info->processID){
        info->processhWnd = hWnd;
        return FALSE;
    }

    return TRUE;
}

И мой цикл:

if(ShellExecuteEx(&shExInfo))
{
    DWORD dwProcessID = GetProcessId(shExInfo.hProcess);

    Porcess_ID_HWND info;
    info.processID = dwProcessID;
    // wait for window to appear
    do
    {
        info.processhWnd = NULL;
        EnumWindows(EnumWindowsProc, (LPARAM)&info);

    } while (!info.processhWnd);

    // wait for window to close
    do
    {
        info.processhWnd = NULL;
        EnumWindows(EnumWindowsProc, (LPARAM)&info);

    } while (info.processhWnd);

    //WaitForSingleObject(shExInfo.hProcess, INFINITE);

    DeleteFile(wsMesh3dx64Parameter.c_str());

    CloseHandle(shExInfo.hProcess);
}

1 ответ

Решение

Нашел хороший ответ на http://forums.codeguru.com/showthread.php?392273-RESOLVED-How-to-get-window-s-HWND-from-it-s-process-handle

1)
ЕСТЬ: Идентификатор процесса, НЕОБХОДИМОСТЬ: Обработка процесса
Решение: OpenProcess()

2)
ИМЕЮТ: Ручка процесса, НЕОБХОДИМОСТЬ: Идентификатор процесса
Решение: GetProcessId()

3)
ЕСТЬ: Оконная ручка, НЕОБХОДИМОСТЬ: Идентификатор процесса
Решение: GetWindowThreadProcessId()

4)
ЕСТЬ: Оконная ручка, НУЖНА: Ручка процесса
Решение: используйте 3), а затем 1)

5)
ЕСТЬ: ID процесса, НУЖНО: дескриптор окна
Решение: EnumWindows(), затем в функции обратного вызова сделайте 3) и проверьте, соответствует ли оно вашему идентификатору процесса.

6)
ИМЕЮТ: Ручка процесса, НУЖНА: Ручка окна
Решение: 2), а затем 5)

так что вы в случае 6. тогда, если никакой идентификатор процесса дескриптора окна не совпадает с идентификатором процесса вашего shExInfo.hProcess, то shExInfo.hProcess не имеет окна

Другие вопросы по тегам