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

接上一篇。

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:

ValueMeaning
0The 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, the CreateProcess function returns without waiting for the child process to finish its initialization. Before trying to communicate with the child process, the parent process can use WaitForInputIdle to determine when the child's initialization has been completed. For example, the parent process should use WaitForInputIdle 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;
} 




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qcyfred

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值