我已经将我的 dll 注入(inject)到进程中。 如何获取主机应用程序的主窗口句柄?
最佳答案
宿主应用程序可能有多个“主窗口”。要检测它们,您可以
- 调用
GetCurrentProcessId
获取当前进程的PID - 调用
EnumWindows
遍历桌面的所有顶层窗口 - 对于桌面上的每个窗口,调用
GetWindowThreadProcessId
获取创建窗口的进程的 PID - 如果窗口的 PID 与您自己进程的 PID 匹配,则记住该窗口。
这会为您提供由您将 DLL 注入(inject)到的进程创建的顶层窗口列表。但是,请注意,这种方法可能会产生在您处理构建的窗口列表时已被销毁的窗口。因此,在对 Windows 进行操作时,请确保使用 IsWindow
。函数以确保手头的窗口仍然有效(这仍然容易出现竞争条件,因为窗口可能在您调用 IsWindow
和实际访问窗口之间变得无效,但时间窗口要小得多)。
这是一个实现该算法的 C++ 函数。它实现了一个 getToplevelWindows
产生 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;
}
更新:最近(我给出答案大约四年后)我也会考虑 traversing the list of threads应用程序,然后使用 EnumThreadWindows
在每个线程上。我注意到在许多情况下这要快得多。
关于c++ - Win32 - 获取应用程序的主窗口句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6202547/