Win32 - Get Main Wnd应用程序句柄

Hoo*_*och 11 c++ windows winapi

我把我的dll注入了进程.如何获取主机应用程序的主窗口句柄?

Fre*_*abe 35

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

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

这将为您提供一个由您注入DLL的进程创建的顶层窗口列表.但请注意,这种方法可能会产生窗口,这些窗口在您处理构建的窗口列表时已被破坏.因此,在对窗口执行某些操作时,请确保使用该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;
}
Run Code Online (Sandbox Code Playgroud)

更新:这些天(我给出答案后大约四年)我还会考虑遍历应用程序的线程列表,然后EnumThreadWindows在每个线程上使用.我注意到在很多情况下这个速度要快得多.

  • 你是我的上帝. (2认同)