读者朋友们可能经常会碰到这样一个问题,想对某些进行操作时,发现这些文档正在被其他程式使用,处于打开状态,而且是被独占打开,这时是没法对文档进行操作的。因此,要想操作这些文档,必须将打开这些文档的进程清除掉。那么如何干净地清除进程呢?其实,在Windows2000操作系统版本中有一个工具程式叫tskill.exe,用他就能够清除掉某个程式的进程,在输入“tskill 程式名”后就能够清除其运行实例。但是如何要在代码里实现tskill的功能该如何做呢?针对这一问题,本实例介绍了在Windows2000下实现的方法。
一、实现方法
在VisualC 编程中,最安全的杀死进程的方法是向运行程式的主窗口发送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、添加代码,编译运行程式。
三、程式代码
//////////////////////////////////////////////////////
#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 < m_count ? m_pids[m_current ] : 0;
}
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 <= m_count);
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
| | 版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2007 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86263408 86263960 86264018 86267838 86262244 86263408 售前咨询:总机转201 202 203 204 205 206 207 208 售后服务:总机转211
212 213 214 217 218 晚上0点以后拔分机225 |
| 财务咨询:总机转224
223 传真:028-86264041 财务QQ: 635483282
售前咨询QQ: 327314358 241975952 275026793 408235859 2182518 499513144 售后服务QQ: 634349278 809071471 307742704 512359778 287976517 363783715 在线咨询
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号
|
|