如何在windows内存中获取进程

源代码在线查看: 如何获取某个进程的主窗口以及创建进程的程序名?.txt

软件大小: 6 K
上传用户: d_zhihua
关键词: windows 内存 进程
下载地址: 免注册下载 普通下载 VIP

相关代码

				如何获取某个进程的主窗口以及创建进程的程序名?
				
				
				
				
				
				
				                   2005年7月15日 星期五 
				                  交换机 动画制作 免费空间 电子商务 笔记本 网站建设 掌上电脑 虚拟主机 路由器 中关村 网页设计 数据库技术
				
				
				
				                  如何获取某个进程的主窗口以及创建进程的程序名?作者:未知 文章来源:本站原创
				
				
				            如何获取某个进程的主窗口以及创建进程的程序名?
				                           
				
				            交换机 | 动画制作 | 免费空间 | 电子商务 | 笔记本 | 网站建设 | 掌上电脑 | 虚拟主机 | 路由器 | 中关村 | 
				            网页设计 | 数据库技术
				
				
				
				                        第一时间提供全球重大新闻
				                        [测试] 三年后你是富翁还是穷光蛋?
				                        [幻灯] 章子怡:理财的最高境界
				                        [新闻] 05财富全球500强出炉
				                        [杂志] 《中国企业家》:陈天桥的“盒子”
				                        [汽车] 爆笑:芙蓉姐姐被撞之后
				                        [幻灯] 比基尼美女惹火身材秀
				                        [论坛] NBA球星:艾弗森和他的汽车
				                        [生活] 复旦大二学生在校经营印务咨询 一年进帐500万
				                        [国际] 日韩着手调查背后 谁把国产啤酒“妖魔化”
				                        [论坛] 中国性意识谋变:性浪潮冲击广大普通人民
				
				                        甲醛  中海油  信用卡  三鹿  走光美女  家居美图  
				
				
				
				
				            下载源代码 
				                
				            在编写工具程序以及系统管理程序的时候。常常需要获取某个进程的主窗口以及创建此进程的程序名。获取主窗口的目的是向窗口发送各种消息。获取启动进程的程序名可以控制对进程的操作。但是有些进程往往有多个主窗口。你要的是哪一个主窗口呢?如果你用过Outlook程序,你就会发现它有多个主窗口,一个窗口列出收件箱和其它文件夹。如果你打开e-mail,便会有另外一个窗口显示信息。它们都是没有父窗口(或者说宿主窗口)的主窗口。运行一下Spy程序,你甚至会发现它们的窗口类名都相同:rctrl_renwnd32。资源管理器(Explorer.exe)也有不止一个主窗口。如图一所示,资源管理器有两个主窗口。一般来讲,想要获取主窗口,凭窗口的式样或类名,你没有什么办法知道哪一个窗口是真正意义上的主窗口。
				            首先我们讨论如何从多个窗口中获取主窗口?其实很容易。利用两个API函数便可以实现。这两个API是 EnumWindows 和 
				            GetWindowThreadProcessId。如果你对这两个函数不熟悉,不要怕,本文提供了一个C++类来对这两个API进行封装。这个类叫 
				            CMainWindowIterator,用它可以枚举某个进程(已知进程ID)的所有主窗口。这正是我们想要的东西。其使用方法如下:
				DWORD pid = // 已知某个进程的ID
				CMainWindowIterator itw(pid);
				for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next()) {
				  // do something
				}        
				            就这么简单,CMainWindowIterator派生于一个更通用的类:CWindowIterator,CWindowIterator负责将::EnumWindows函数打包以隐藏回调细节。它有一个虚拟函数OnWindow,你可以在派生类中重写这个函数,从而可以用任何方式来枚举窗口。CMainWindowIterator就是重写了OnWindow函数,让它只获取属于某个给定进程的主窗口: 
				
				// (在构造函数中设置m_pid)
				BOOL CMainWindowIterator::OnWindow(HWND hwnd)
				{
				  if ((GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE)) {
				    DWORD pidwin;
				    GetWindowThreadProcessId(hwnd, &pidwin);
				    if (pidwin==m_pid)
				      return TRUE;
				  }
				  return FALSE;
				}这两个类的定义如下:(对应的文件是 EnumProc.h 和 EnumProc.cpp) 
				//////////////////////////////////////////////////////
				// 这个类主要是封装::EnumWindows,列举顶层窗口
				//
				class CWindowIterator {
				protected:
					HWND*	m_hwnds;		// 隶属于某个进程PID窗口句柄数组
					DWORD m_nAlloc;			// 数组大小
					DWORD m_count;			// 找到的窗口句柄数
					DWORD m_current;		// 当前的窗口句柄
					static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp);
				
					// 虚拟枚举函数
					virtual BOOL OnEnumProc(HWND hwnd);
				
					// 在派生中改写此函数来过滤不同种类的窗口
					virtual BOOL OnWindow(HWND hwnd) {
						return TRUE;
					}
				
				public:
					CWindowIterator(DWORD nAlloc=1024);
					~CWindowIterator();
					
					DWORD GetCount() { return m_count; }
					HWND First();
					HWND Next() {
						return m_hwnds && m_current 					}
				};
				
				////////////////////////////////////
				// 列举某个进程的顶层窗口
				//
				class CMainWindowIterator : public CWindowIterator  {
				protected:
					DWORD m_pid;		// 进程ID
					virtual BOOL OnWindow(HWND hwnd);
				public:
					CMainWindowIterator(DWORD pid, DWORD nAlloc=1024);
					~CMainWindowIterator();
				};图一是用上述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: 
				
				DWORD count;
				HMODULE hm[1];
				EnumProcessModules(hProcess, hm, 1, &count);      然后调用GetModuleFileNameEx。
				            实际上从前面的图一中可以看到,在lp.exe程序中我们已经实现了罗列进程及其对应的模块名。程序的实现细节中还用到了PSAPI输出的API函数EnumProcesses来枚举所有运行进程,为了对具体的细节进行封装,我如法炮制编写了与CWindowIterator 
				            和CMainWindowIterator类似的两个C++类:CProcessIterator 和 
				            CProcessModuleIterator ,它们分别对EnumProcesses 和EnumProcessModules 
				            API函数进行了封装。有了这两个打包类,一切都变得如此简单。 
				CProcessIterator itp;
				for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
				  // 处理每一个进程
				}下面是获取创建进程的EXE文件名的方法: 
				CProcessModuleIterator itm(pid);
				HMODULE hModule = itm.First(); // .EXE
				TCHAR modname[_MAX_PATH];
				GetModuleBaseName(itm.GetProcessHandle(), hModule, modname, _MAX_PATH);    
				            因为lp显示出来的并不是一个含全路径的模块文件名,所以我用另外一个PSAPI函数GetModuleBaseName来代替GetModuleFileNameEx从而获取全路径名。此外,由于CProcessModuleIterator自己会打开进程枚举模块,所以不必调用OpenProcess。用CProcessModuleIterator::GetProcessHandle可以得到已打开进程的句柄。lp程序还用CMainWindowIterator来显示每个特定进程的所有主窗口。下面是CProcessIterator 
				            和 CProcessModuleIterator的定义: 
				////////////////////////////////////////////////////////////////////////////////////////
				// 进程列举类 -- 列举出系统中的所有进程,但总是跳过第一个PID=0的进程,即空闲进程(IDLE)
				//
				class CProcessIterator {
				protected:
					DWORD*	m_pids;			// 包含进程IDs的数祖
					DWORD		m_count;	// 数组大小
					DWORD		m_current;	// 当前数组项
				public:
					CProcessIterator();
					~CProcessIterator();
				
					DWORD GetCount() { return m_count; }
					DWORD First();
					DWORD Next() {
						return m_pids && m_current 					}
				};
				
				/////////////////////////////////////////////////////////////////
				// 列举某个进程的模块,第一个模块就是创建此进程的主exe程序
				//
				class CProcessModuleIterator {
				protected:
					HANDLE	m_hProcess;			// 进程句柄
					HMODULE*	m_hModules;		// 模块句柄数组
					DWORD		m_count;		// 数组大小
					DWORD		m_current;		// 当前模块的句柄
				public:
					CProcessModuleIterator(DWORD pid);
					~CProcessModuleIterator();
				
					HANDLE GetProcessHandle()	{ return m_hProcess; }
					DWORD GetCount()				{ return m_count; }
					HMODULE First();
					HMODULE Next() {
						return m_hProcess && m_current < m_count ? m_hModules[m_current++] : 0;
					}
				};     
				
				
				
				
				            文章录入:知秋一叶    责任编辑:知秋一叶  
				            上一篇文章: 干干净净杀死进程
				
				            下一篇文章: 共享内存封装类
				
				            【字体:小 大】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 
				
				                  拍MV愈想完美愈心寒 刘德华遇山洪急逃命(图)
				                  被骗3000万疑为炒作 杭天琪频繁约会神秘富商
				                  杨千嬅变38D“大胸” 穿超短裙戏院示众(图)
				                  看女F4前面波涛汹涌 背景大有来头 中国女篮60-55击败奥运亚军澳大利亚[图]
				                  中国女排两连败 陈忠和微笑无法承受之重
				                  跳远名将全裸拍写真 赛车女郎完美身段
				                  莎娃性感出击 艳光盖过花花公子兔女郎[图] 
				                  古月  写真  韩剧  走光  史密斯夫妇  姚明年  世界大战  六月影讯  大话体坛  体育贴图  减肥论坛  
				                  北京2008  足球  NBA  电游  
				
				
				
				              网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
				                没有任何评论 
				
				
				       
				
				                          
				
				                        相关文章列表
				
				                  VBA:轻松定制ERP
				
				                  VB.NET的数据库基础编程 (2)
				
				                  用VB.Net编写通用报表组件 (5
				
				                  用VB.Net编写通用报表组件 (4
				
				                  用VB.Net编写通用报表组件 (3
				
				                  用VB.Net编写通用报表组件 (2
				
				                  用VB.Net编写通用报表组件 (1
				
				                  VB.NET的数据库基础编程 (1)
				
				                  用VB.NET来做个性化浏览器
				
				                  使用VB创建服务器端组件
				
				
				
				                        最新热门文章
				
				                        安全路由器组网及IPSec技术介绍
				                        布线应注意的十个问题(二)
				                        布线应注意的十个问题(一)
				                        中小学校园网方案推荐
				                        家庭无线网络
				                        ISDN路由器连入中小型网
				                        横纵开合摩托罗拉MPx专区惊天问
				                        配置和维护ApacheWEBServer
				                        关于Apache服务器配置技巧
				                        Apache与Tomcat安装配置手册
				
				
				
				                        最新推荐文章
				
				                        热门技巧天天递招 98篇(二十六
				                        [组图]FREEHAND实例——绘制足
				                        [组图]Illustrator渐变网格入门
				                        [组图]Adobe Illustrator 封套
				                        [组图]Adobe Illustrator 10的
				                        [组图]Adobe Illustrator中的简
				                        [组图]Adobe Illustrator 9.0 
				                        [组图]3D/VR游戏制作软件GameS
				                        [组图]Anark教程:使3D对象看起
				                        [组图]3Dmax4的Cult3D输出插件
				
				
				
				
				
				
				
				
				
				      | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 |
				
				            Copyright © 2005 100j.net . All Rights Reserved
				            百极网 版权所有 desperado@100j.net 广告联系:QQ 67453010
				            本站所有资源均来自互联网,如有侵犯您的版权或其他问题,请通知管理员,我们会尽快处理!
				
				
							

相关资源