Windows程序设计(4):根据PID,获取句柄Handle

来源:互联网 发布:淘宝发货地怎么设置 编辑:程序博客网 时间:2024/05/21 17:29

接上一篇。

Review:Windows程序设计(3):程序启动器(CreateProcess)

再说一遍需求:写一个程序A,去启动一个指定的程序B,设置它的窗口大小并把它放到指定位置。


既然CreateProcess指定的程序启动参数,对于GUI程序无效(我暂时真的不知道为什么…),那可以让程序启动以后,获取它的Handle,然后模拟操作系统向它发送消息,让其响应。


CreateProcess可以得到被启动的程序的PID,但得不到handle。(我也不知道怎么回事,明明说返回的是个handle,但确实和B的handle不是一个数,另外尝试了各种办法,比如openProcess返回的也不是B的handle的数)


那么,如果根据PID找到它对应的handle呢?


方法一,调用GetWindowThreadProcessId函数。

有可能有死循环…,就是可能一直都找不到。

一个坑!

如果开启的不是gui程序,只是开个控制台,也找不到!启动以后,CreateProcess立即返回了。wait那个函数没有生效!就算是Sleep以后,也找不到……

vc++6.0编译,xp系统和win8系统,测试通过。

注意,因为前面是getForeground,所以后面是写GetNextWindow的参数传的是Prev…

有几个函数,getWindow,getTopWindow,getForeground...

GetNext...的参数有prev、next。


GetWindowThreadProcessId

The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.

DWORD GetWindowThreadProcessId(  HWND hWnd,             // handle to window  LPDWORD lpdwProcessId  // address of variable for process identifier); 

Parameters

hWnd
Handle to the window.
lpdwProcessId
Pointer to a 32-bit value that receives the process identifier. If this parameter is not NULL,GetWindowThreadProcessId copies the identifier of the process to the 32-bit value; otherwise, it does not.

Return Values

The return value is the identifier of the thread that created the window.  


WaitForInputIdle

The WaitForInputIdle function waits until the given process is waiting for user input with no input pending, or until the time-out interval has elapsed.

The WaitForInputIdle function only works with GUI applications. If a console application calls the function, it returns immediately, with no wait.

DWORD WaitForInputIdle(  HANDLE hProcess,       // handle to process  DWORD dwMilliseconds   // time-out interval in milliseconds); 

Parameters

hProcess
Handle to the process.
dwMilliseconds
Specifies the time-out interval, in milliseconds. If dwMilliseconds is INFINITE, the function does not return until the process is idle.

Return Values

The following table shows the possible return values:

ValueMeaning0The wait was satisfied successfully.WAIT_TIMEOUTThe wait was terminated because the time-out interval elapsed.0xFFFFFFFFAn error occurred. To get extended error information, use the GetLastError function.

Remarks

The WaitForInputIdle function enables a thread to suspend its execution until a specified process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronizing a parent process and a newly created child process. When a parent process creates a child process, theCreateProcess function returns without waiting for the child process to finish its initialization. Before trying to communicate with the child process, the parent process can useWaitForInputIdle to determine when the child's initialization has been completed. For example, the parent process should useWaitForInputIdle before trying to find a window associated with the child process.

The WaitForInputIdle function can be used at any time, not just during application startup. 


方法二,调用EnumWindows函数。枚举窗口。

有个问题需要注意。

如果启动的不是GUI,waitForInputldle没有用。需要手动指定一个Sleep的时间。或者就用B向A发消息通知一下。或者B启动完毕后在哪个地方标记一下,内存也好硬盘也好,然后A去轮询这个位置。 

废话不多说了,上代码。

#include <windows.h>#include <stdio.h>BOOL CALLBACK EnumWindowsProc(HWND hwnd,      // handle to parent window  LPARAM lParam   // application-defined value  ){if (IsWindowVisible(hwnd)) {char title[1000];GetWindowText(hwnd,title,1000);printf("%s\n",title);unsigned long find_pid = 0;GetWindowThreadProcessId(hwnd, &find_pid);if(find_pid == lParam){printf("已找到\n");printf("%s, 0x%x, %d\t",title, hwnd,lParam);}// printf("%d, %d\n", find_pid, lParam);}return TRUE;}int main (int argc,char* argv[]){char szCommandLine[]="calc.exe";STARTUPINFO si={sizeof(si)};PROCESS_INFORMATION pi;si.dwY = 0;si.dwX = 0;si.dwXSize = 200;si.dwYSize = 100;si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USEPOSITION | STARTF_USESIZE; //制定wShowWindow成员si.wShowWindow=TRUE; //为真,显示进程的主窗口BOOL bRet=::CreateProcess(NULL,//不在此指定可执行文件的文件名szCommandLine, //命令行参数NULL,//默认进程的安全性NULL,//默认线程的安全性FALSE,//指定当前进程内的句柄不可以被子进程继承CREATE_NEW_CONSOLE,//为新进程创建一个新的控制台窗口NULL,//使用本进程的环境变量NULL,//使用本进程的驱动器和目录&si,&pi);if(bRet){WaitForInputIdle(pi.hProcess,INFINITE);Sleep(1000);EnumWindows(EnumWindowsProc,pi.dwProcessId);::CloseHandle(pi.hThread);::CloseHandle(pi.hProcess);printf("新的进程的进程ID号:%d\n",pi.dwProcessId);printf("新进程的主线程ID号:%d\n",pi.dwThreadId);}return 0;}