您的位置:首页 > 其它

通过进程ID获得该进程主窗口的句柄

2012-02-26 12:00 911 查看
一个进程可以拥有很多主窗口,也可以不拥有主窗口,所以这样的函数是不存在的,所幸的是,相反的函数是有的。所以我们可以调用EnumWindows来判断所有的窗口是否属于这个进程。
typedef struct tagWNDINFO

...{

DWORD dwProcessId;

HWND hWnd;

} WNDINFO, *LPWNDINFO;

BOOL CALLBACK YourEnumProc(HWND hWnd,LPARAM lParam)

...{

DWORD dwProcessId;

GetWindowThreadProcessId(hWnd, &dwProcessId);

LPWNDINFO pInfo = (LPWNDINFO)lParam;

if(dwProcessId == pInfo->dwProcessId)

...{

pInfo->hWnd = hWnd;

return FALSE;

}

return TRUE;

}

HWND GetProcessMainWnd(DWORD dwProcessId)

...{

WNDINFO wi;

wi.dwProcessId = dwProcessId;

wi.hWnd = NULL;

EnumWindows(YourEnumProc,(LPARAM)&wi);

return wi.hWnd;

}

如果这个进程没有窗口,函数返回NULL

经试验,在宿主窗口中调用GetProcessMainWnd( GetCurrentProcessId() )后得到的窗口句柄有时确实是该窗口的句柄,但有时得到的却是DLL的窗口的句柄,而在DLL的窗口过程中调用GetProcessMainWnd( GetCurrentProcessId() )只得到DLL窗口的句柄,并不能得到宿主窗口的句柄。【将dll直接注入执行注入代码的exe中进行测试】

将该代码做如下修改后,能得到正确的宿主窗口句柄:

typedef struct tagWNDINFO

...{

DWORD dwProcessId;

HWND hWnd;

HWND Dll_hwnd;

} WNDINFO, *LPWNDINFO;

BOOL CALLBACK YourEnumProc(HWND hWnd, LPARAM lParam)

...{

DWORD dwProcessId;

GetWindowThreadProcessId(hWnd, &dwProcessId);

LPWNDINFO pInfo = (LPWNDINFO)lParam;

if( (dwProcessId == pInfo->dwProcessId) && (hWnd != pInfo->Dll_hwnd) )

//确认找到的句柄不是DLL窗口的句柄

//如果找到的是DLL窗口的句柄则返回FALSE以便继续查找宿主的窗口句柄

...{

pInfo->hWnd = hWnd;

return FALSE;

}

return TRUE;

}

HWND GetProcessMainWnd(DWORD dwProcessId, HWND Dll_hwnd)

//将DLL窗口的句柄传入,以便识别找到的句柄不是DLL窗口的句柄

...{

WNDINFO wi;

wi.dwProcessId = dwProcessId;

wi.hWnd = NULL;

wi.Dll_hwnd = Dll_hwnd;

EnumWindows(YourEnumProc,(LPARAM)&wi);

HWND re_hwnd = wi.hWnd;

while( GetParent(re_hwnd) != NULL )

//循环查找父窗口,以便保证返回的句柄是最顶层的窗口句柄

...{

re_hwnd = GetParent( re_hwnd );

}

return re_hwnd;

}

在DLL的窗口过程中调用GetProcessMainWnd( GetCurrentProcessId(), this->m_hWnd )即可获得宿主窗口的句柄。

【备注】如果宿主进程已经调用了其它DLL并且该DLL也创建有窗口,那么,我想这个代码并不能保证得到的句柄不是其它DLL的窗口句柄,要做进一步的识别,我想,靠这个方法还是难以实现的了,或许可以考虑在注入DLL时(或注入之后?)传递该宿主窗口的句柄给DLL。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: