通过进程号的ID获得窗口的句柄
最近几天,工作的需要,打算实现将别人编译好的exe程序,通过自己的程序去调用,然后根据程序中得到的ID号,去得到此进程运行创建的窗口句柄,在网上搜了一段时间,得到了不少启示,再结合自己的实际环境,整合出了以下三种方法,以下将针对每一种方法做出简单的介绍同时给出关键代码,本人所采用的平台为vc6.0,英文企业版。
在介绍方法之前,首先需要介绍下,在自己的程序中运行编译好的exe方法,网上搜搜会得到不少启示,主要就是三个API函数(WinExec,ShellExecute ,CreateProcess,可以实现调用其他程序的要求,其中以WinExec最为简单,ShellExecute比WinExec灵活一些,CreateProcess最为复杂。) 本人在实际的开发环境中采用的是 CreateProcess 方法,至于该方法各参数的详细说明与使用,请参考msdn上的讲解。以下是我运行exe的代码。
</pre><p align="left"> </p><div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><strong>[cpp]</strong> <a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/wawj522527/article/details/7946656#">view plain</a><a target=_blank class="CopyToClipboard" title="copy" href="http://blog.csdn.net/wawj522527/article/details/7946656#">copy</a><a target=_blank class="PrintSource" title="print" href="http://blog.csdn.net/wawj522527/article/details/7946656#">print</a><a target=_blank class="About" title="?" href="http://blog.csdn.net/wawj522527/article/details/7946656#">?</a></div></div><ol class="dp-cpp"><li class="alt"><span><span>STARTUPINFO si; </span><span class="comment">//启动进程参数 </span><span> </span></span></li><li><span>PROCESS_INFORMATION pi; </span><span class="comment">//进程信息结构 </span><span> </span></li><li class="alt"><span> </span></li><li><span> </span></li><li class="alt"><span></span><span class="datatypes">LPSTR</span><span> FileName=sProcessName.GetBuffer(0); </span><span class="comment">//全路径 </span><span> </span></li><li><span> </span></li><li class="alt"><span></span><span class="comment">//结构清零 </span><span> </span></li><li><span>ZeroMemory(&si,</span><span class="keyword">sizeof</span><span>(si)); </span><span class="comment">//此参数必须清零 </span><span> </span></li><li class="alt"><span>ZeroMemory(&pi,</span><span class="keyword">sizeof</span><span>(pi)); </span><span class="comment">//此参数必须清零 </span><span> </span></li><li><span>si.dwFlags =STARTF_USESHOWWINDOW;</span><span class="comment">//隐藏创建的窗口 </span><span> </span></li><li class="alt"><span>si.wShowWindow=SW_HIDE;</span><span class="comment">//隐藏创建的窗口 </span><span> </span></li><li><span> </span></li><li class="alt"><span></span><span class="comment">//创建进程 </span><span> </span></li><li><span></span><span class="datatypes">BOOL</span><span> flag=CreateProcess( </span></li><li class="alt"><span> FileName, </span><span class="comment">//创建的进程, </span><span> </span></li><li><span> NULL, </span></li><li class="alt"><span> NULL, </span></li><li><span> NULL, </span></li><li class="alt"><span> </span><span class="keyword">false</span><span>, </span></li><li><span> 0, </span></li><li class="alt"><span> NULL, </span></li><li><span> NULL, </span></li><li class="alt"><span> &si, </span></li><li><span> &pi); </span></li><li class="alt"><span></span><span class="keyword">if</span><span>(flag==0) </span></li><li><span>{ </span></li><li class="alt"><span> </span><span class="keyword">return</span><span>; </span></li><li><span>} </span></li><li class="alt"><span> </span></li><li><span></span><span class="comment">//等待进程,直到其退出。 </span><span> </span></li><li class="alt"><span>WaitForSingleObject(pi.hProcess,INFINITE); </span></li><li><span> </span></li><li class="alt"><span></span><span class="comment">//关闭句柄 </span><span> </span></li><li><span> </span><span class="datatypes">BOOL</span><span> flag1=CloseHandle(pi.hThread ); </span></li><li class="alt"><span></span><span class="datatypes">BOOL</span><span> flag2=CloseHandle(pi.hProcess ); </span></li></ol></div><pre style="DISPLAY: none" class="cpp" name="code"> STARTUPINFO si; //启动进程参数
PROCESS_INFORMATION pi; //进程信息结构
LPSTR FileName=sProcessName.GetBuffer(0); //全路径
//结构清零
ZeroMemory(&si,sizeof(si)); //此参数必须清零
ZeroMemory(&pi,sizeof(pi)); //此参数必须清零
si.dwFlags =STARTF_USESHOWWINDOW;//隐藏创建的窗口
si.wShowWindow=SW_HIDE;//隐藏创建的窗口
//创建进程
BOOL flag=CreateProcess(
FileName, //创建的进程,
NULL,
NULL,
NULL,
false,
0,
NULL,
NULL,
&si,
&pi);
if(flag==0)
{
return;
}
//等待进程,直到其退出。
WaitForSingleObject(pi.hProcess,INFINITE);
//关闭句柄
BOOL flag1=CloseHandle(pi.hThread );
BOOL flag2=CloseHandle(pi.hProcess );
- 根据得到的pi结构,可以得到运行的exe的进程号。
- 法:
根据得到的pi结构,可以得到运行的exe的进程号。
第一种方法:
利用FindWindow()api函数,此函数声明为:
- HWND FindWindow(
- LPCTSTR lpClassName, // class name
- LPCTSTR lpWindowName // window name
- );
HWND FindWindow(
LPCTSTR lpClassName, // class name
LPCTSTR lpWindowName // window name
);
使用该api前提,是需要知道创建窗口的类名或者窗口的标题,一般来说,窗口的类名师不容易得到,一般用的参数是窗口的标题。此函数返回值就是窗口的句柄。此方法比较简单,这里不再赘述。
第二种方法:
利用EnumWindows与GetWindowThreadProcessId 这两个API函数。具体实现的代码如下:
- typedef struct EnumFunArg
- {
- HWND hWnd;
- DWORD dwProcessId;
- }EnumFunArg,*LPEnumFunArg;
- BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
- {
- EnumFunArg *pArg = (LPEnumFunArg)lParam;
- DWORD processId;
- GetWindowThreadProcessId(hwnd, &processId);
- if( processId == pArg->dwProcessId)
- {
- pArg->hWnd = hwnd;
- return TRUE;
- }
- return FALSE;
- }HWND ReturnWnd(DWORD processID)
- {
- HWND retWnd=NULL;
- EnumFunArg wi;
- wi.dwProcessId =processID;
- wi.hWnd = NULL;
- EnumWindows(lpEnumFunc,(LPARAM)&wi);
- if(wi.hWnd){ retWnd=wi.hWnd;
- } return retWnd;
- }
typedef struct EnumFunArg
{
HWND hWnd;
DWORD dwProcessId;
}EnumFunArg,*LPEnumFunArg;
BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
{
EnumFunArg *pArg = (LPEnumFunArg)lParam;
DWORD processId;
GetWindowThreadProcessId(hwnd, &processId);
if( processId == pArg->dwProcessId)
{
pArg->hWnd = hwnd;
return TRUE;
}
return FALSE;
}HWND ReturnWnd(DWORD processID)
{
HWND retWnd=NULL;
EnumFunArg wi;
wi.dwProcessId =processID;
wi.hWnd = NULL;
EnumWindows(lpEnumFunc,(LPARAM)&wi);
if(wi.hWnd){ retWnd=wi.hWnd;
} return retWnd;
}
将此部分代码添加到程序中,直接调用相关的函数,就能得到窗口的句柄。
第三种方法:
利用GUITHREADINFO以及GetGUIThreadInfo。具体的代码如下:
- #include <winuser.h>
- #include <winable.h>
- #include <windows.h>
- HWND g_Hwnd=null;
- GUITHREADINFO gui;
- WaitForInputIdle(pi.hProcess,INFINITE);
- FillMemory(&gui,sizeof(GUITHREADINFO),0);
- gui.cbSize=sizeof(GUITHREADINFO);
- if (GetGUIThreadInfo(pi.dwThreadId,&gui))
- {
- //DWORD errorcode=GetLastError();
- if (gui.hwndActive ){
- g_Hwnd= gui.hwndActive;
- }
- }
#include <winuser.h>
#include <winable.h>
#include <windows.h>
HWND g_Hwnd=null;
GUITHREADINFO gui;
WaitForInputIdle(pi.hProcess,INFINITE);
FillMemory(&gui,sizeof(GUITHREADINFO),0);
gui.cbSize=sizeof(GUITHREADINFO);
if (GetGUIThreadInfo(pi.dwThreadId,&gui))
{
//DWORD errorcode=GetLastError();
if (gui.hwndActive ){
g_Hwnd= gui.hwndActive;
}
}
第三种方法相对来讲比较简单一些,但编译时一定要注意,三个头文件,不能少。