我注入了我的DLL进程。 我怎样才能得到主机应用程序的主窗口句柄?
主机应用程序可能有多个“主窗口”。 要发现他们,你可以
GetCurrentProcessId
来获取当前进程的PID EnumWindows
遍历桌面的所有顶层窗口 GetWindowThreadProcessId
来获取创建该窗口的进程的PID 这给你一个顶级窗口的列表,由您注入DLL的过程创建。 但是,请注意,这种方法可能会产生窗口,这些窗口在处理构建的窗口列表时已经被破坏。 因此,在使用窗口进行某些操作时,一定要使用IsWindow
函数来确保手边的窗口仍然有效(这仍然很容易出现竞争状态,因为在调用IsWindow
和实际访问窗口之间窗口可能变得无效,但时间窗口要小得多)。
这是一个实现这个算法的C ++函数。 它实现了一个getToplevelWindows
函数,该函数生成一个包含当前进程所有顶层窗口std::vector<HWND>
的std::vector<HWND>
。
struct EnumWindowsCallbackArgs { EnumWindowsCallbackArgs( DWORD p ) : pid( p ) { } const DWORD pid; std::vector<HWND> handles; }; static BOOL CALLBACK EnumWindowsCallback( HWND hnd, LPARAM lParam ) { EnumWindowsCallbackArgs *args = (EnumWindowsCallbackArgs *)lParam; DWORD windowPID; (void)::GetWindowThreadProcessId( hnd, &windowPID ); if ( windowPID == args->pid ) { args->handles.push_back( hnd ); } return TRUE; } std::vector<HWND> getToplevelWindows() { EnumWindowsCallbackArgs args( ::GetCurrentProcessId() ); if ( ::EnumWindows( &EnumWindowsCallback, (LPARAM) &args ) == FALSE ) { // XXX Log error here return std::vector<HWND>(); } return args.handles; }
更新:这些天(我给了答案后大约四年),我还会考虑遍历应用程序的线程列表,然后在每个线程上使用EnumThreadWindows
。 我注意到这在很多情况下是相当快的。