如何获取某个进程的主窗口以及创建进程的程序名(进程映像名)
来源:互联网 发布:python日期的加减 编辑:程序博客网 时间:2024/05/09 15:51
在编写工具程序以及系统管理程序的时候。常常需要获取某个进程的主窗口以及创建此进程的程序名。获取主窗口的目的是向窗口发送各种消息。获取启动进程的程序名可以控制对进程的操作。但是有些进程往往有多个主窗口。你要的是哪一个主窗口呢?如果你用过Outlook程序,你就会发现它有多个主窗口,一个窗口列出收件箱和其它文件夹。如果你打开e-mail,便会有另外一个窗口显示信息。它们都是没有父窗口(或者说宿主窗口)的主窗口。运行一下Spy程序,你甚至会发现它们的窗口类名都相同:rctrl_renwnd32。资源管理器(Explorer.exe)也有不止一个主窗口。如图一所示,资源管理器有两个主窗口。一般来讲,想要获取主窗口,凭窗口的式样或类名,你没有什么办法知道哪一个窗口是真正意义上的主窗口。
首先我们讨论如何从多个窗口中获取主窗口?其实很容易。利用两个API函数便可以实现。这两个API是 EnumWindows 和 GetWindowThreadProcessId。如果你对这两个函数不熟悉,不要怕,本文提供了一个C++类来对这两个API进行封装。这个类叫 CMainWindowIterator,用它可以枚举某个进程(已知进程ID)的所有主窗口。这正是我们想要的东西。其使用方法如下:
就这么简单,CMainWindowIterator派生于一个更通用的类:CWindowIterator,CWindowIterator负责将::EnumWindows函数打包以隐藏回调细节。它有一个虚拟函数OnWindow,你可以在派生类中重写这个函数,从而可以用任何方式来枚举窗口。CMainWindowIterator就是重写了OnWindow函数,让它只获取属于某个给定进程的主窗口:
这两个类的定义如下:(对应的文件是 EnumProc.h 和 EnumProc.cpp)
图一是用上述C++类编写的一个控制台程序lp.exe的输出画面。最后两栏分别是对应进程的“窗口句柄”和“类名/窗口标题”。其命令行开关“/ct”表示列出窗口类名(c)和窗口标题(t)。
图一
一般来讲,如果隶属于某个进程的窗口没有可见的父窗口,那么这个窗口就可以认为是此进程的主窗口。对WS_VISIBLE的检查很重要,因为有些应用创建多个不可见的顶层窗口。关于CMainWindowIterator类的使用细节请参见本文的例子源代码。
接下来我们来讨论如何获取创建进程的程序文件名。有人用各种方法尝试过,比如:GetModuleFileName,GetModuleInstance 和 GetModuleHandle,好像都不行。为什么呢?其实,方法是没错,但调用这些函数得到的只是当前正在运行的这个进程已经加载的模块名(modules),不能用于获取其它进程所加载的模块。因此,必须想别的办法,首先要考虑两种情况,一种是如果你写的程序在Windows NT,Windows 2000,Windows XP环境运行,则可以使用PSAPI,这是一个Windows操作系统中比较新的DLL,利用其中输出的API函数可以获取进程和模块的详细信息。另一种是如果你写的程序在Windows 9x或者Windows Me中运行,则必须借助于ToolHelp,限于本文的篇幅,我在这里不介绍如何使用ToolHelp,如果你感兴趣的话可以参考,MSDN的技术支持文章Q175030,题目为“如何在Win32中枚举应用程序”。
PSAPI中有一个函数是GetModuleFileNameEx。它通过某个进程和模块句柄作为参数来获得模块名。那么对于某个进程来说,你怎么知道哪个模块是启动进程的执行文件呢呢?PSAPI中的另一个函数EnumProcessModules将某个进程中所有模块的模块句柄填充到一个数组中。这个数组的第一个元素便是主模块的句柄,所以你用下面的代码来得到第一个HMODULE:
然后调用GetModuleFileNameEx。
实际上从前面的图一中可以看到,在lp.exe程序中我们已经实现了罗列进程及其对应的模块名。程序的实现细节中还用到了PSAPI输出的API函数EnumProcesses来枚举所有运行进程,为了对具体的细节进行封装,我如法炮制编写了与CWindowIterator 和CMainWindowIterator类似的两个C++类:CProcessIterator 和 CProcessModuleIterator ,它们分别对EnumProcesses 和EnumProcessModules API函数进行了封装。有了这两个打包类,一切都变得如此简单。
下面是获取创建进程的EXE文件名的方法:
因为lp显示出来的并不是一个含全路径的模块文件名,所以我用另外一个PSAPI函数GetModuleBaseName来代替GetModuleFileNameEx从而获取全路径名。此外,由于CProcessModuleIterator自己会打开进程枚举模块,所以不必调用OpenProcess。用CProcessModuleIterator::GetProcessHandle可以得到已打开进程的句柄。lp程序还用CMainWindowIterator来显示每个特定进程的所有主窗口。下面是CProcessIterator 和 CProcessModuleIterator的定义:
- 如何获取某个进程的主窗口以及创建进程的程序名(进程映像名)
- 如何获取某个进程的主窗口以及创建进程的程序名?
- 如何获取某个进程的主窗口以及创建进程的程序名?
- 如何获取某个进程的主窗口以及创建进程的程序名?
- 如何获取某个进程的主窗口以及创建进程的程序名?
- 如何获取某个进程的主窗口以及创建进程的程序名?
- Windows 下 根据进程名获取进程ID 以及该进程下所有窗口的句柄
- 如何知道某个进程名所对应的进程号
- 如何通过进程pid获取进程名、可执行文件的名称
- 获取进程名,获取进程路径,获取当前进程的窗口句柄。
- AU3-进程名获取窗口名
- 根据进程名或窗口标题杀进程及创建进程的函数
- 如何通过进程ID获取进程名
- 结束指定窗口名的进程
- 根据进程名获取进程PID以及进程
- 根据Handle获取进程名的方法
- Android获取组件的进程名
- 获取进程名的两种方法
- django中flatepages简单应用
- MFC控件关联变量的类型
- 20140409收盘小结
- 花自然开放,娇艳欲滴的美丽
- JXL将excel的数据导入到数据库
- 如何获取某个进程的主窗口以及创建进程的程序名(进程映像名)
- PHP 增加与删除数组元素
- powerpc家族谱系详解
- POJ 2155 Matrix (二维树状数组)
- 手机滚屏页面下拉自动加载内容
- SPOJ1748 - SEQPAR2 二分答案 DP优化 单调队列+线段树
- IOS开发入门基本知识——(UIButton UIView UILabel的创建)
- Ext.MessageBox.show()方法的使用
- 使用Cocos2D-x引擎在Mac下开发运行在iOS设备上的《植物大战僵尸》第一篇