How to get hWnd of window opened by ShellExecuteEx.. hProcess?

Peter.O picture Peter.O · Jul 17, 2010 · Viewed 13.1k times · Source

This "simple" issue seems to be fraught with side issues.
eg. Does the new process open multiple windows; Does it have a splash screen?
Is there a simple way? (I'm starting a new instance of Notepad++)

...
std::tstring  tstrNotepad_exe = tstrProgramFiles + _T("\\Notepad++\\notepad++.exe");

SHELLEXECUTEINFO SEI={0};
sei.cbSize       = sizeof(SHELLEXECUTEINFO);
sei.fMask        = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd         = hWndMe;  // This app's window handle
sei.lpVerb       = _T("open");
sei.lpFile       = tstrNotepad_exe.c_str();     
sei.lpParameters = _T(" -multiInst -noPlugins -nosession -notabbar ";   
sei.lpDirectory  = NULL;
sei.nShow        = SW_SHOW;
sei.hInstApp     = NULL;    
if( ShellExecuteEx(&sei) )
{ // I have sei.hProcess, but how best to utilize it from here?
}
...

Answer

Jon Benedicto picture Jon Benedicto · Jul 17, 2010

First use WaitForInputIdle to pause your program until the application has started and is waiting for user input (the main window should have been created by then), then use EnumWindows and GetWindowThreadProcessId to determine which windows in the system belong to the created process.

For example:

struct ProcessWindowsInfo
{
    DWORD ProcessID;
    std::vector<HWND> Windows;

    ProcessWindowsInfo( DWORD const AProcessID )
        : ProcessID( AProcessID )
    {
    }
};

BOOL __stdcall EnumProcessWindowsProc( HWND hwnd, LPARAM lParam )
{
    ProcessWindowsInfo *Info = reinterpret_cast<ProcessWindowsInfo*>( lParam );
    DWORD WindowProcessID;

    GetWindowThreadProcessId( hwnd, &WindowProcessID );

    if( WindowProcessID == Info->ProcessID )
        Info->Windows.push_back( hwnd );

    return true;
}

....

if( ShellExecuteEx(&sei) )
{
    WaitForInputIdle( sei.hProcess, INFINITE );

    ProcessWindowsInfo Info( GetProcessId( sei.hProcess ) );

    EnumWindows( (WNDENUMPROC)EnumProcessWindowsProc,
        reinterpret_cast<LPARAM>( &Info ) );

    // Use Info.Windows.....
}