Win32 - 获取应用程序的主 Wnd 句柄

时间:2023-04-12
本文介绍了Win32 - 获取应用程序的主 Wnd 句柄的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我已将我的 dll 注入进程.如何获取宿主应用程序的主窗口句柄?

I have injected my dll into process. How can I get Main window handle of host application?

推荐答案

宿主应用程序可能有多个主窗口".要检测它们,您可以

The host application may have multiple 'main windows'. To detect them, you could

  1. 调用 GetCurrentProcessId获取当前进程的PID
  2. 调用 EnumWindows遍历桌面的所有顶级窗口
  3. 对于桌面上的每个窗口,调用 GetWindowThreadProcessId获取创建窗口的进程的PID
  4. 如果窗口的 PID 与您自己进程的 PID 匹配,请记住该窗口.

这为您提供了由您注入 DLL 的进程创建的顶级窗口列表.但是,请注意,这种方法可能会产生在您处理构建的窗口列表时已被破坏的窗口.因此,在使用 Windows 执行某些操作时,请确保使用 IsWindow 函数以确保手头的窗口仍然有效(这仍然容易出现竞争条件,因为在您调用 IsWindow 和实际访问窗口,但时间窗口要小得多).

That gives you a list of toplevel windows created by the process which you injected your DLL into. However, please note that this approach may yield windows which have been destroyed by the time you process the constructed list of windows. Hence, when doing something with the windows, make sure to use the IsWindow function to ensure that the window at hand is still valid (this is still prone to race conditions since the window may become invalid between your call to IsWindow and actually accessing the window, but the time window is much smaller).

这是一个实现该算法的 C++ 函数.它实现了一个 getToplevelWindows 函数,该函数产生一个 std::vector,其中包含当前进程的所有顶级窗口的句柄.

Here's a C++ function implementing this algorithm. It implements a getToplevelWindows function which yields a std::vector<HWND> containing the handles of all toplevel windows of the current process.

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 在每个线程上.我注意到这在许多情况下要快得多.

UPDATE: These days (about four years after I gave the answer) I would also consider traversing the list of threads of the application and then using EnumThreadWindows on each thread. I noticed that this is considerably faster in many cases.

这篇关于Win32 - 获取应用程序的主 Wnd 句柄的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!