2015-05-05 4 views
0

Я использую 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); на петлю, которая проверяет, владеет ли внешний процесс окном, а если не завершает его.

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

UPDATE:

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

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); 
} 

ответ

3

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

 
1) 
HAVE: Process ID, NEED: Process handle 
Solution: OpenProcess() 

2) 
HAVE: Process handle, NEED: Process ID 
Solution: GetProcessId() 

3) 
HAVE: Window handle, NEED: Process ID 
Solution: GetWindowThreadProcessId() 

4) 
HAVE: Window handle, NEED: Process handle 
Solution: Use 3) and then 1) 

5) 
HAVE: Process ID, NEED: Window handle 
Solution: EnumWindows(), then in the callback function do 3) and check if it matches your process ID. 

6) 
HAVE: Process handle, NEED: Window handle 
Solution: 2) and then 5) 

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