分享
 
 
 

在Visual C++应用程序中彻底清除进程

王朝vc·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

读者朋友们可能经常会碰到这样一个问题,想对某些进行操作时,发现这些文件正在被其它程序使用,处于打开状态,而且是被独占打开,这时是没法对文件进行操作的。因此,要想操作这些文件,必须将打开这些文件的进程清除掉。

那么如何干净地清除进程呢?其实,在Windows2000操作系统版本中有一个工具程序叫tskill.exe,用它就可以清除掉某个程序的进程,在输入"tskill 程序名"后就可以清除其运行实例。但是如何要在代码里实现tskill的功能该如何做呢?针对这一问题,本实例介绍了在Windows2000下实现的方法。

一、实现方法

在Visual C++编程中,最安全的杀死进程的方法是向运行程序的主窗口发送WM_CLOSE消息,其实现代码如下:

HWND hwnd =this.m_hWnd; // 获得主窗口

PostMessage(hwnd, WM_CLOSE, 0, 0);

发送此消息后,通常应该等待直到进程确实终止,当进程终止时,它发出状态信号,并且 WaitForSingleObject 返回WAIT_OBJECT_0。假如返回别的值,进程要么挂起了,要么仍然在进行处理。在这种情况下,杀死这个进程的唯一方法是用功能更强大的API函数:TerminatePRocess()。假如想干得漂亮一点,可以在关闭之前向主窗口发送一个WM_QUERYENDsession消息,当用户结束会话(log out)或者调用ExitWindows()函数时,应用程序会收到这个消息,然后预备退出进程,此时一般都会弹出一个确认对话框,告诉用户:"程序要推出了,假如要保存修改的东西,现在是最佳时机,想保存吗?"有三种选择(Yes/No/Cancel)。此外,发送WM_QUERYENDSESSION消息可以拒绝推出进程(按下"Cancel键"),假如是这样,进程将会延续。

假如想要关闭的进程被挂起,使用SendMessageTimeout()函数就非常重要,而不是用SendMessage()函数,其参数SMTO_NOTIMEOUTIFNOTHUNG是一个只有windows 2000 和Windows xp才有的标志。其意义是"假如线程没有挂起,不要超时",换句话说就是假如线程正在进行正常处理,那么永远等待,以便用户能看到对话框并决定做什么,当用户最终做出决定后,SendMessageTimeout()将带着相应的bOKToKill值返回。

本例为了增强代码的可重用性,将实现细节都封装在一个叫CFindKillProcess的类中,包括查找和杀死进程,详情请参见EnumProc.h和EnumProc.cpp文件。文件中还有另外两个可重用类,一个是CProcessIterator,另一个是CWindowIterator。

CfindKillProcess类的成员函数FindProcess()查找某个进程序,假如找到这个进程,它返回此进程的ID,然后将此ID传给CFindKillProcess::KillProcess()函数,KillProcess()函数封装了关闭窗口以及终止逻辑,它利用CmainWindowIterator类对象来枚举进程的主窗口(可能不止一个,见"如何获取某个进程的主窗口以及创建进程的程序名?"),并发送WM_CLOSE到每一个窗口,然后等待进程死亡。它有一个布尔型参数用来指示当应用程序进程不愿意退出时是否执行TerminateProcess()函数。具体细节请参见下载的代码。

二、编程步骤

1、 启动Visual C++6.0,生成一个控制台应用程序,将该程序命名为"kp";

2、 在程序代码中添加CfindKillProcess、CProcessIterator类的定义;

3、 添加代码,编译运行程序。

更多内容请看C/C++技术专题 C/C++进阶技术文档 C/C++应用实例专题,或

三、程序代码

///////////////////////////////////////////////////////////////////////////////////////////

#pragma once

//////////////////

// Process iterator -- iterator over all system processes

// Always skips the first (IDLE) process with PID=0.

class CProcessIterator {

protected:

DWord* m_pids; // array of proCSSor IDs

DWORD m_count; // size of array

DWORD m_current; // next array item

public:

CProcessIterator();

~CProcessIterator();

DWORD First();

DWORD Next() {

return m_pids && m_current

}

DWORD GetCount() {

return m_count;

}

};

//////////////////

// Handy class to facilitate finding and killing a process by name.

class CFindKillProcess {

public:

CFindKillProcess();

~CFindKillProcess();

DWORD FindProcess(LPCTSTR lpModname, BOOL bAddExe=TRUE);

BOOL KillProcess(DWORD pid, BOOL bZap);

};

///////////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "EnumProc.h"

// CProcessIterator - Iterates all processes

CProcessIterator::CProcessIterator()

{

m_pids = NULL;

}

CProcessIterator::~CProcessIterator()

{

delete [] m_pids;

}

//////////////////

// Get first process: Call EnumProcesses to init array. Return first one.

DWORD CProcessIterator::First()

{

m_current = (DWORD)-1;

m_count = 0;

DWORD nalloc = 1024;

do {

delete [] m_pids;

m_pids = new DWORD [nalloc];

if (EnumProcesses(m_pids, nalloc*sizeof(DWORD), &m_count)) {

m_count /= sizeof(DWORD);

m_current = 1; // skip IDLE process

}

} while (nalloc

return Next();

}

////////////////////////////////////////////////////////////////

// CFindKillProcess - to find/kill a process by module name.

//

CFindKillProcess::CFindKillProcess()

{}

CFindKillProcess::~CFindKillProcess()

{}

//////////////////

// Search for process whose module name matches parameter.

// Finds "foo" or "foo.exe"

DWORD CFindKillProcess::FindProcess(LPCTSTR modname, BOOL bAddExe)

{

CProcessIterator itp;

for (DWORD pid=itp.First(); pid; pid=itp.Next()) {

TCHAR name[_MAX_PATH];

CProcessModuleIterator itm(pid);

HMODULE hModule = itm.First(); // .EXE

if (hModule) {

GetModuleBaseName(itm.GetProcessHandle(),hModule, name, _MAX_PATH);

string sModName = modname;

if (strcmpi(sModName.c_str(),name)==0)

return pid;

sModName += ".exe";

if (bAddExe && strcmpi(sModName.c_str(),name)==0)

return pid;

}

}

return 0;

}

//////////////////

// Kill a process cleanly: Close main windows and wait.

// bZap=TRUE to force kill.

BOOL CFindKillProcess::KillProcess(DWORD pid, BOOL bZap)

{

CMainWindowIterator itw(pid);

for (HWND hwnd=itw.First(); hwnd; hwnd=itw.Next()) {

DWORD bOKToKill = FALSE;

SendMessageTimeout(hwnd, WM_QUERYENDSESSION, 0, 0,SMTO_ABORTIFHUNGSMTO_NOTIMEOUTIFNOTHUNG,100, &bOKToKill);

if (!bOKToKill)

return FALSE; // window doesn't want to die: abort

PostMessage(hwnd, WM_CLOSE, 0, 0);

}

// I've closed the main windows; now wait for process to die.

BOOL bKilled = TRUE;

HANDLE hp=OpenProcess(SYNCHRONIZEPROCESS_TERMINATE,FALSE,pid);

if (hp) {

if (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0) {

if (bZap) { // didn't die: force kill it if zap requested

TerminateProcess(hp,0);

} else {

bKilled = FALSE;

}

}

CloseHandle(hp);

}

return bKilled;

}

//////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "EnumProc.h"

#define tpf _tprintf // to save typing

typedef list

CStringList; // like MFC, but with STL

// pre-declare functions

int help();

// check for switch: / or -

inline BOOL isswitch(TCHAR c) { return c==L'/' c==L'-'; }

int main(int argc, TCHAR* argv[], TCHAR* envp[])

{

CStringList cmdargs; // command-line args (processes to kill)

BOOL bDisplayOnly=FALSE; // don't kill, just show results

BOOL bQuiet=FALSE; // suppress error messages

BOOL bZap=FALSE; // force-kill process

// Parse command line. Switches can come in any order.

for (int i=1; i

if (isswitch(argv[i][0])) {

for (UINT j=1; j

switch(tolower(argv[i][j])) {

case '?': help(); return 0;

case 'n': bDisplayOnly=TRUE; break;

case 'q': bQuiet=TRUE; break;

case 'z': bZap=TRUE; break;

default:

return help();

}

}

} else {

cmdargs.push_back(argv[i]); // got a non-switch arg: add to list

}

}

if (cmdargs.size()

help();

// Now iterate args (module names), killing each one

CStringList::iterator it;

for (it=cmdargs.begin(); it!=cmdargs.end(); it++) {

CFindKillProcess fkp;

DWORD pid = fkp.FindProcess(it-

c_str());

if (pid) {

if (bDisplayOnly) {

tpf(_T("Kill process %d(0x%08x)\n"),pid,pid);

} else {

fkp.KillProcess(pid, bZap);

}

} else if (!bQuiet) {

tpf(_T("Error: Can't find process '%s'.\n"),it-

c_str());

}

}

return 0;

}

int help()

{

tpf(_T("kp: Kill process from command line.\n"));

tpf(_T(" Copyright 2002 Paul DiLascia.\n\n"));

tpf(_T(" kp [/nqz?] modname1 [modname2....]\n"));

tpf(_T(" where modnameN is a module name; eg foo or foo.exe\n"));

tpf(_T("\n"));

tpf(_T(" /n(othing) don't kill, just show results\n"));

tpf(_T(" /q(uiet) don't show errors\n"));

tpf(_T(" /z(ap) force kill (ignore WM_QUERYENDSESSION)\n"));

tpf(_T("\n"));

return 0;

}

四、小结

本实例通过介绍CfindKillProcess类探讨了在Windows2000下彻底消除进程的方法,虽然该程序只能在Windows2000环境下编译运行,但是该方法对Windows98下进程的控制也是有借鉴意义的

更多内容请看C/C++技术专题 C/C++进阶技术文档 C/C++应用实例专题,或

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有