要对进程进行某种操作,就必须首先知道该进程的进程句柄或者进程ID,否则一切无从谈起,对于程序自己创建的子进程来说,CreateProcess函数返回了进程句柄和进程ID,但如果需要调试系统中已经运行的进程,那就必须首先获取它们的句柄才行。Win32中并没有直接获取其他进程句柄的函数,但如果知道进程ID,可以由此得到进程句柄,所以可以首先通过某种途径获取进程ID。

一、获取进程ID

1. 从窗口句柄获取进程句柄

获取进程ID的方法之一是使用GetWindowThreadProcessId函数,这个函数可以从一个窗口句柄获得创建该窗口的进程的进程ID,而通过FindWindow函数得到窗口句柄是很简单的,所以GetWindowThreadProcessId函数的用途相当广泛。该函数的用法是:

DWORD GetWindowThreadProcessId(

HWND hWnd,             // handleto window

LPDWORD lpdwProcessId  // processidentifier

);

其中hWnd参数指定需要用来获取进程ID的窗口句柄,lpdwProcessId指向一个双字变量,函数在这里返回创建窗口的进程ID,函数的返回值是目标进程中创建该窗口的线程的线程句柄(一个有用的副产品!)。

 

2. 通过快照来获取进程ID

每一个应用程序实例在运行起来后都会在当前系统下产生一个进程,大多数应用程序均拥有可视界面,用户可以通过标题栏上的关闭按钮关闭程序。但是也有为数不少的在后台运行的程序是没有可视界面的,对于这类应用程序用户只能通过CTRL+ALT+DEL热键呼出"关闭程序"对话框显示出当前系统进程列表,从中可以结束指定的任务。显然,该功能在一些系统监控类软件中还是非常必需的,其处理过程大致可以分为两步:借助系统快照实现对系统当前进程的枚举和根据枚举结果对进程进行管理。本文下面即将对此过程的实现进行介绍。

  当前进程的枚举

  要对当前系统所有已开启的进程进行枚举,就必须首先获得那些加载到内存的进程当前相关状态信息。在Windows操作系统下,这些进程的当前状态信息不能直接从进程本身获取,系统已为所有保存在系统内存中的进程、线程以及模块等的当前状态的信息制作了一个只读副本--系统快照,用户可以通过对系统快照的访问完成对进程当前状态的检测。在具体实现时,系统快照句柄的获取是通过Win32 API函数CreateToolhelp32Snapshot()来完成的,通过该函数不仅可以获取进程快照,而且对于堆、模块和线程的系统快照同样可以获取。该函数原型声明如下:

HANDLE WINAPICreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID);

  其中,参数dwFlags:指定将要创建包含哪一类系统信息的快照句柄,本程序中只需要检索系统进程信息,因此可将其设置为 TH32CS_SNAPPROCESS;函数第二个参数th32ProcessID`则指定了进程的标识号,当设置为0时指定当前进程。如果成功函数将返回一个包含进程信息的系统快照句柄。在得到快照句柄之后只能以只读的方式对其进行访问。至于对系统快照句柄的使用同普通对象句柄的使用并没有什么太大区别,在使用完之后也需要通过CloseHandle()函数将其销毁。

  在得到系统的快照句柄后,就可以对当前进程的标识号进行枚举了,通过这些枚举出的进程标识号可以很方便的对进程进行管理。进程标识号通过函数 Process32First() 和 Process32Next()而得到,这两个函数可以枚举出系统当前所有开启的进程,并且可以得到相关的进程信息。这两个函数原型声明如下:

BOOL WINAPI Process32First(HANDLEhSnapshot, LPPROCESSENTRY32 lppe);

BOOL WINAPI Process32Next(HANDLEhSnapshot,LPPROCESSENTRY32 lppe);

  以上两个函数分别用于获得系统快照中第一个和下一个进程的信息,并将获取得到的信息保存在指针lppe所指向的PROCESSENTRY32结构中。函数第一个参数hSnapshot为由CreateToolhelp32Snapshot()函数返回得到的系统快照句柄;第二个参数lppe为指向结构 PROCESSENTRY32的指针,PROCESSENTRY32结构可对进程作一个较为全面的描述,其定义如下:

typedef struct tagPROCESSENTRY32 {

DWORD dwSize; // 结构大小;

DWORD cntUsage; // 此进程的引用计数;

DWORD th32ProcessID; // 进程ID;

DWORD th32DefaultHeapID; // 进程默认堆ID;

DWORD th32ModuleID; // 进程模块ID;

DWORD cntThreads; // 此进程开启的线程计数;

DWORD th32ParentProcessID; // 父进程ID;

LONG pcPriClassBase; // 线程优先权;

DWORD dwFlags; // 保留;

char szExeFile[MAX_PATH]; // 进程全名;

} PROCESSENTRY32;

  以上三个API函数均在头文件tlhelp32.h中声明,运行时需要有kernel32.lib库的支持。通过这三个函数可以枚举出当前系统已开启的所有进程,并可获取到进程的各相关信息,下面给出一个简单的应用示例。在此示例中将枚举出系统的所有进程,并逐个比较进程名,查找需要的进程信息。如果有,则返回进程ID,否则返回 -1。

pid_t CProbeCMaster::is_process_running(constchar* process_name)

{

pid_t process_id = -1;

#ifdef ACE_WIN32

HANDLE Snapshot;

Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

//获得某一时刻系统的进程、堆(heap)、模块(module)或线程的快照信息

PROCESSENTRY32 processListStr;

processListStr.dwSize = sizeof(PROCESSENTRY32);

BOOL return_value;

return_value = Process32First(Snapshot,&processListStr);

//获得系统进程链表中第一个进程的信息

while(return_value)

{

if( ACE_OS::strcmp(process_name, processListStr.szExeFile) == 0 )

{//比较进程名,如果此进程与传入的进程名相同,那么就找到了需要的进程信息

process_id = processListStr.th32ProcessID;

break;

}

return_value = Process32Next(Snapshot, &processListStr);

//获得系统进程链表中下一个进程的信息

}

CloseHandle( Snapshot );

#endif

return process_id;

}

二、获取进程的句柄

得到了进程ID以后,就可以通过OpenProcess函数来获取该进程的句柄了。

HANDLE OpenProcess(

DWORD dwDesiredAccess,  // accessflag

BOOL bInheritHandle,    // handleinheritance option

DWORD dwProcessId       // processidentifier

);

函数的参数定义如下:

●   dwDesiredAccess——指定需要对该进程进行的操作,要对目标进程进行某种操作,必须指定操作代码,但是在Windows NT操作系统中,对其他进程操作需要有相应的权限,如需要结束目标进程就必须有PROCESS_TERMINATE权限才行,当权限不够的时候,打开进程的操作就会失败。一般来说,除了系统进程以外,可以对其他进程进行任何操作,操作码可以是以下取值的组合:

■   PROCESS_ALL_ACCESS——等于下面全部操作码的组合。

■   PROCESS_CREATE_THREAD——允许创建远程线程。

■   PROCESS_DUP_HANDLE——允许进程句柄被复制。

■   PROCESS_QUERY_INFORMATION——允许使用GetExitCodeProcess函数查询进程的退出码或使用GetPriorityClass函数查询进程的优先级。

■   PROCESS_SET_INFORMATION——允许使用SetPriorityClass函数设置进程的优先级。

■   PROCESS_TERMINATE——允许终止进程。

■   PROCESS_VM_OPERATION—允许使用WriteProcessMemory函数或VirtualProtectEx函数修改进程的地址空间。

■   PROCESS_VM_READ——允许对进程的地址空间进行读操作。

■   PROCESS_VM_WRITE——允许对进程的地址空间进行写操作。

●   bInheritHandle——指明返回的进程句柄是否可以被当前进程的子进程继承,如果参数指定为TRUE,则句柄可以被继承。

●   dwProcessId——指定目标进程的进程ID。

如果函数执行成功,返回值是被打开的进程句柄。如果函数执行失败则返回NULL。一般打开失败的原因是由权限不够引起的。当完成对目标进程的操作以后,必须使用CloseHandle将获得的句柄关闭。

三、对进程的管理

  在得到各枚举进程的标识号后就可以实现对进程的管理了,由于被管理进程在当前进程之外,因此必须首先通过OpenProcess()函数来获取一个已经存在的进程对象的句柄,然后才可以通过该句柄对指定的进程进行管理和控制。在OpenProcess()函数的调用时把进程标识号作为参数传入, OpenProcess()函数的原型声明如下:

HANDLE OpenProcess(DWORD dwDesiredAccess,// 访问标志

BOOL bInheritHandle, // 处理继承的标志

DWORD dwProcessId // 进程标识号);

  如果函数执行成功将返回由进程标识号指定的进程对象句柄。下面同样也对其给出一个简单的应用示例,在此示例中根据所获取的进程对象句柄通过TerminateProcess()函数将指定的进程终止:

// 查看"test.ext"进程是否存在,如果存在则返回它的进程ID

pid_t process_id =is_process_running("test.exe");

if ( process_id > 0 )

{

// 利用进程的ID值,打开该进程,获得进程句柄

HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE,data);

// 检测句柄的有效性,如有效则终止该进程

if (hProcess)

TerminateProcess(hProcess,0);

}

  由于需要在调用TerminateProcess()函数终止进程时确保进程句柄可有效使用,因此在前面调用OpenProcess()时,需要指定其访问标致为PROCESS_TERMINATE。

WIN32进程快照以及进程ID和句柄查找相关推荐

  1. 获取进程或线程的ID以及句柄信息

    先介绍一下创建线程或进程的时候是可以得到相应的ID以及句柄信息的. BOOL CreateProcess ( LPCTSTR lpApplicationName, LPTSTR lpCommandLi ...

  2. win32根据进程名获取进程ID或者终止进程

    第一部分: 根据进程名获取进程ID. 首先我们需要了解三个windows API函数: HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags,DWO ...

  3. windows 获取当前进程/线程的ID、句柄和内核地址

    获取当前进程 / 线程的 ID .句柄和内核地址 在用户态( RING3 )和内核态( RING0 )下,获取这些值的函数是不同的,而且这些函数的实现原理也是不同的,下面做个小结: 1. 用户态( R ...

  4. 易语言通过进程名称获取进程ID

    通过系统映像的名称来获取进程的PID,有了PID就可以通过(进程_ID取窗口句柄) 获取窗口句柄,有了句柄就可以大漠后台绑定窗口,所以最终目的还是通过进程名称来获取进程所在窗口的句柄,用来窗口的绑定操 ...

  5. linux之ps命令--进程快照

    linux中的ps命令可以列出当前在运行的进程的快照,就是执行ps命令时有哪些进程在执行以及他们是什么状态, 如果想动态地显示进程信息,就可以使用top命令. 进程一般存在几种状态, 1.运行(R)  ...

  6. 511遇见易语言模块API教程进程结束和进程取自进程ID

    当我们多线程多窗口启动游戏时,在退出时我们手动比较麻烦,可以使用进程结束一键退出. 511遇见易语言模块API教程 1.GetCurrentProcessId 获取当前进程一个唯一的标识符 说明: 获 ...

  7. Linux进程全解3——进程概念、进程ID、多进程调度原理

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 1.什么是进程? (1)动态过程而不是静态实物: (2)进程就是程序的一次运行过程. 比如一个静态的可执行程序a. ...

  8. linux进程号为一,一步步探究linux进程中的用户ID

    转载请注明来源chengyaogen.blog.chinaunix.net 一.进程与权限 A.进程时Linux/Unix操作系统中最重要的抽象之一 B.进程是一个处于执行期的程序(目标代码存储在某种 ...

  9. 通过Docker进程pid获取容器id

    虽然Docker是通过namespace隔离技术实现容器间进程的隔离,但在运行Docker的主机中,Docker容器内的进程与主机内运行的进程是在同一个namespace(假设叫A)的.虽然在Dock ...

最新文章

  1. SWIG,C#沟通C++的桥梁
  2. php采集列表xml代码,php读取xml列表程序
  3. bzoj4034: [HAOI2015]树上操作
  4. mysql 外键有啥用途_Mysql外键是什么?有哪些用处?(图文+视频)
  5. mysql使用从c3p0_使用c3p0連接池操作mysql數據庫中文亂碼解決辦法
  6. 乐易家智能机器人价格_安川焊接机器人价格多少钱?核心是质量好
  7. 关刀机器人_小学机器人活动总结
  8. Spark精华问答 | spark性能优化方法
  9. 软件测试工程师笔试总结
  10. jdbc 连接 mysql 的字符串
  11. staruml怎么画协作图_er图怎么画?轻松绘制专业er图的软件
  12. 项目经理应该具备的四种能力
  13. ORA-12162错误解决
  14. 网易2016在线笔试小结
  15. android定时启动 tasker,Android 神器 Tasker 个人的一些配置
  16. 不是谁多情,亦不是谁薄情
  17. Docker一键部署MySQL
  18. DTI数据TBSS组间统计对比设计矩阵
  19. 超强的ChatGPT会成为下一代搜索引擎吗?
  20. layaari2-cmd 踩坑记录,解决安装失败问题

热门文章

  1. 变成机器人 尼尔机械纪元_尼尔机械纪元机器人啪啪
  2. Word文档打开密码的设置与取消
  3. [非线性控制理论]4_反馈线性化_反步法
  4. Vuex中浏览器安装devtools
  5. suite No.1 , BWV 1007, In G:Prelude
  6. 根据用户输入编码,输出课程名称
  7. C语言四层电梯控制系统,单片机四层电梯控制系统(课程设计).doc
  8. 常见的交互式分析(Interactive Analytics)和开发工具
  9. Landmark Recognition Using VGG16 Training
  10. 天空卫士监控行为显示叉_SkyGuard 天空卫士-内部威胁防护领导者