你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
用 Windows API编程中止正在运行的程序
 

  :本文用Windows的进程查找、进程中止等API函数实现了任意中止系统中正在运行的进程的功能,并对进程操作中所用到的数据结构作了简要介绍。

主题词API函数    进程控制

 

Windows是一种抢占式多任务的操作系统,在Windows运行时按下Ctrl+Alt+Del时会出现关闭程序对话框,我们能在任何时候中止一个选定的程序,就是这种抢占式多任务特点的具体体现,现在我们就讨论一下这种机制的实现原理,并编程实现相同的功能。

Windows中引进了进程的概念,进程指的是程序的一次执行过程。在内存中,进程对应着一段程序及一个数据结构――进程序控制块,它用来描述进程的各种特性,并唯一地标识一个进程。与DOS的内存控制块相似,内存中的进程控制块被组织成为队列,如果我们能遍历这个队列,然后选中其中的一个进程,中止该进程,也就可以实现与关闭程序对话框一样的功能。Windows的各种编程语言都不直接提供这样的操作,只能通过调用WindowsAPI函数来实现。

有两个函数可用于查找系统中的进程,Process32First函数查找系统中的第一个进程,Process32Next用于查找其他进程,先调用一次Process32First,然后反复调用Process32Next,就可以找出系统中的所有进程,这两个函数说明在tlhelp32.h中,调用函数的文件中要打开这个头文件。函数的原型为:

BOOL Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);

BOOL Process32Next(HANDLE hSnapshot,  LPPROCESSENTRY32 lppe);

函数带有两个参数,这两个参数要在调用这两个函数之前生成,首先要用以下函数建立一个快照句柄,

HANDLE CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID );

该函数有两个变量,dwFlags是查找的类型,它规定了即将要查找的对象,该变量常见的取是如下两种:,

TH32CS_SNAPPROCESS    进程查找

    TH32CS_SNAPTHREAD    线程查找
    在进行进程和线程查找时,th32ProcessID参数置0即可。
然后要定义一个PROCESSENTRY32型变量,PROCESSENTRY32是一个结构类型,其具体内容在MSDN中可以查到,该结构相当于进程控制块,Process32FirstProcess32Next函数将查找到的进程的特性记录在这个变量中。结构中与本程序有关的内容如下:
    typedef struct tagPROCESSENTRY32 {
    DWORD dwSize;//该结构的长度 
    …… 
    DWORD th32ProcessID;//进程标识符 
    …… 
    char szExeFile[MAX_PATH]; //程序的路径及文件名
} PROCESSENTRY32; 

typedef PROCESSENTRY32 *  PPROCESSENTRY32;
如果能得到进程的句柄,可用函数TerminateProcess中止一个进程,该函数说明如下:

BOOL TerminateProcess(
  HANDLE hProcess, // 进程的句柄
  UINT uExitCode   // 进程的退出码
);
PROCESSENTRY32中只有进程的标识符,所以还要通过如下函数取得进程的句柄:
HANDLE OpenProcess(
  DWORD dwDesiredAccess,  // 存取标志
  BOOL bInheritHandle,    // 是否使用继承的句柄
  DWORD dwProcessId       // 进程标识符
);
以上是与程序有关的准备知识,现在我们就可以用上述的函数构造一个能中止任意进程的程序了。具体操作和编程过程如下。
AppWizard生成一个基于对话框的新的工程(在生成过程的第一步选Dialog Based),本例工程名起名为proclist ,对话框的标题改为“进程中止”;在对话框中加入“刷新”、“中止”两按键,并分别赋以标识符IDC_REFRESHIDC_STOP, 并为“中止”按键建立变量名m_stop;加入一个ClistCtrl控件,适当调整其大小,命以变量m_list 
proclistDlg.cpp的中的#include "proclistDlg.h"后加上#include "tlhelp32.h"
在函数CProclistDlg::OnInitDialog()中加入如下斜体字所示的语句
BOOL CProclistDlg::OnInitDialog()
{  …………
   m_list.InsertColumn(0,"                             ",LVCFMT_LEFT,300,0);//在列表空制控件中加入一列
   m_stop.EnableWindow (FALSE);/使中止按钮无效
   OnRefresh();/刷新列表控制控件中的内容,列出系统中的所有进程
return TRUE;  
}
ClassWizard生成OnItemchangedList1函数,当用鼠标在列表控制控件中选中一行时,将发送LVN_ITEMCHANGED消息,该函数就是该消息的映射函数,将函数体作如下改变,以使得当有行被选中时,中止按钮会有效。
void CProclistDlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
    m_stop.EnableWindow (TRUE);         
}
OnRefresh()函数是“刷新”按钮按下消息的映射函数,用于刷新列表控制控件中的内容,他遍历系统中所有的进程,并将其文件名列入列表中。
void CProclistDlg::OnRefresh() 
{
    HANDLE      hProcessSnap   = NULL;
   PROCESSENTRY32 pe32           = {0};
   m_list.DeleteAllItems ();//删除列表中所有的进程名
   hProcessSnap =(HANDLE)CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   pe32.dwSize = sizeof(PROCESSENTRY32); 
   Process32First(hProcessSnap, &pe32);//查找第一个进程
    do  {  
      m_list.InsertItem(0,pe32.szExeFile);/将进程名加入列表
     }
   while (Process32Next(hProcessSnap, &pe32));
//查找下一个进程,直到所有的进程处理完
   CloseHandle (hProcessSnap);//关闭句柄
}
OnStop()函数是“中止”按键按下消息的映射函数。
void CProclistDlg::OnStop() 
{ char ItemText[70],procname[50];
  lstrcpy(procname, m_list.GetItemText(m_list.GetNextItem( -1, LVNI_ALL | LVNI_SELECTED),0));/得到当前选中的进程的程序名
  wsprintf(ItemText,"真的要中止%s吗?",procname);
  HANDLE      hProcessSnap   = NULL;
  PROCESSENTRY32 pe32           = {0};
  hProcessSnap =(HANDLE)CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  pe32.dwSize = sizeof(PROCESSENTRY32); 
  Process32First(hProcessSnap, &pe32);/搜索该进程
 do  { 
if (strstr(pe32.szExeFile,procname)) //找到,用以下语句中止该进程
       { if (MessageBox(ItemText,"警告",MB_YESNO)==IDYES)   
          if(TerminateProcess(OpenProcess(0,FALSE,pe32.th32ProcessID),0))
                             {  MessageBox("中止成功","提示");
                                OnRefresh();}/删除后立即刷新
          else MessageBox("中止失败","提示");
          break;   }
 }  while (Process32Next(hProcessSnap, &pe32));
 CloseHandle (hProcessSnap);  
 m_stop.EnableWindow (FALSE);
}
该函数中从列表中得到进程的文件名,再用进程程序名搜索进程,取得进程的ID,然后中止进程。这样做的目的是为了节省代码,虽然用Clist来管理已搜索到的进程,可以免去二次查找进程的,但增加了对链表维护的代码。
运行这个程序,出现如下所示窗体,在列表中列出了系统中驻留的全部进程的文件名,选定一个程序,按“中止”按钮,就可以中止选定的进程,列表中的内容随之改变;运行一些程序,再按下“刷新“按钮,这些程序的文件名也会反映在列表中。
 
 
 
 
  
  
  
  
  
  
  
  
  
  
  
  
 
 
 

 
 
本程序所用硬件为P400  CPU64M内存,在Windows  98操作系统、VC++6.0环境下实现了中止任意程序的功能。

 

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089