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

Visual Studio 中的 C++ 入门 Visual Studio 中的 C++ 入门 *** 若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档。 通过完成本演练,你将熟悉在使用 Visual Studio 开发应用程序时可使用的许多工具和对话框。 当你了解了在集成开发环境 (IDE) 中工作的更... 阅读详情
读者朋友们可能经常会碰到这样一个问题,想对某些进行操作时,发现这些文件正在被其它程序使用,处于打开状态,而且是被独占打开,这时是没法对文件进行操作的。因此,要想操作这些文件,必须将打开这些文件的进程清除掉。那么如何干净地清除进程呢?其实,在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、 添加代码,编译运行程序。

 ///////////////////////////////////////////////////////////////////////////////////////////
  #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);
  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_ABORTIFHUNG|SMTO_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(SYNCHRONIZE|PROCESS_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() <=0)
  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下进程的控制也是有借鉴意义的。

Visual C++中SDI应用程序启动顺序         Visual C++的AppWizad为Developers建立窗口应用程序提供了很大的方便,但对于MFC(Mircosoft Foundation Class)初学者来说,了解由AppWizad生成的一系列类和函数的功能、启动过程及各类、各函数间的关系不是一件容易的事情。本文企图让读者明白由AppWizad生成的类和函数的启动顺序和过程。假设读者已经了解基于消息的窗口应用程序的工 阅读详情

相关推荐

Visual C++ 2005 Express Edition开发Win32应用程序

九月初九 重阳1. 下载Visual C++ 2005 Express Editionhttp://msdn.microsoft.com/vstudio/express/visualc/download/离线安装的完整安装iso文件,包括所有所需组件:http://download.microsoft.com/download/A/9/1/A91D6B2B-A798-47DF-9C7E-A9785

工匠 1472

vc下删除当前运行exe

vc下删除当前运行exe 也就是杀掉自己 xp和2000下都运行正常

Visual Studio 2008 C++实现进程隐藏技术

Windows API(应用程序编程接口)是一系列用于与Windows操作系统交互的函数。它包括用于进程管理、内存管理、文件系统访问等多个方面的函数。在进程隐藏中,主要关注的API涉及进程枚举、进程信息检索、进程控制等。这些API可以大致分为两类:一类用于枚举系统中的进程,如和;另一类用于获取和修改进程信息,如和。

weixin_31163455的博客 1098

C++卸载程序功能示例

C++写一个自己的卸载程序来完成程序的卸载工作,同时运行后要删除卸载程序本身,并删除卸载程序所在的文件夹

DEVC++的卸载

DEVC++的卸载

ouyangqing的专栏 6857

C/C++代码中创建销毁进程【内附可执行源码注释完整】

🚀本文将通过介绍如何使用代码进行进程创建以及销毁以及相关概念,并且提供可执行源码作为参考

Jacksqh的博客 1076

删除 exe 本身(自删除)

<br />// KillMySelf.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> BOOL DeleteMyself(WCHAR *pHelper) { int ret; WCHAR helper[MAX_PATH]; ZeroMemory(helper, sizeof(

Lewis's Space 949

VC EXE程序删除自身

在开发程序过程中,有许多情况中都需要执行程序自己把自己从物理磁盘上删除,例如,卸装程序,一些黑客程序获取信息后自清除等,我们把这些具有自删除功能的程序统称为“自杀”程序。对于一名程序员,想必都有在程序中使用代码删除物理磁盘文件的经历吧,我们只需要简单的调用DeleteFile API函数就可以搞定,但是该函数并不能删除自己,当它执行删除自己时...

weixin_33711647的博客 1601

【免费下载】 微软Visual C++ 2015运行时库:轻松运行C++应用程序的必备工具

微软Visual C++ 2015运行时库:轻松运行C++应用程序的必备工具 【下载地址】MicrosoftVisualC2015Redistributablex64x86安装包下载 本仓库提供Microsoft Visual C++ 2015 Redistributable x64/x86安装包的下载。该安装包包含了V...

gitblog_09722的博客 4457

Visual C++ 桌面通讯录应用程序实战

Visual C++是微软推出的集成开发环境(IDE),它为开发者提供了一个强大的工具,用于创建、编辑、编译、调试和部署Windows平台的应用程序。这个章节将带您了解Visual C++的基础知识,包括它的安装、界面布局以及项目管理等核心功能。MFC,即Microsoft Foundation Classes,是微软公司为简化Windows应用程序开发而提供的一套C++类库。它的出现标志着微软在推动Windows应用程序开发便捷化方面迈出了重要的一步。

weixin_36149538的博客 1242

【免费下载】 Visual C++ Redistributable for Visual Studio 2015:轻松解决运行时依赖问题

Visual C++ Redistributable for Visual Studio 2015:轻松解决运行时依赖问题 【下载地址】VisualCRedistributableforVisualStudio2015下载仓库 Visual C++ Redistributable for Visual Studio 20...

gitblog_09775的博客 9155

使用 Visual Studio 2022 开发 Linux C++ 应用程序

使用 Visual Studio 2022 开发 Linux C++ 应用程序

ltimaginea的博客 1万+

Visual C++ 6.0简介与创建控制台应用程序和MFC应用程序

1.Visual C++ 6.0开发环境简介 Visual C++ 6.0(以下简称VC 6.0)是功能强大、可视化开发Windows应用程序的IDE(Integrated Developing Environment)。它集代码编辑、调试、编译和可视化资源编辑等功能于一体。 2.创建控制台应用程序 ①创建新项目,选择Win32 Console Application程序,命名为Firs

呵呵。。。 9441

Visual Studio 2019安装以及编写第一个c++控制台应用程序

Visual Studio 2019安装以及编写第一个c++控制台应用程序

pc915968220的博客 3万+

Visual C++开发数据库应用程序

Visual C++开发数据库应用程序  [ 作者:ldc    转贴自:本站原创    点击数:89    更新时间:2004-4-23    文章录入:ldc311 ]  1、 概述1、1 Visual C++开发数据库技术的特点Visual C++提供了多种多样的数据库访问技术——ODBC API、MFC ODBC、DAO、OLE DB、ADO等。这些技术各有自己的特点,它们提供了

Corey的专栏 4271

【免费下载】 Microsoft Visual C++ 2015 Redistributable x64/x86安装包下载

Microsoft Visual C++ 2015 Redistributable x64/x86安装包下载 【下载地址】MicrosoftVisualC2015Redistributablex64x86安装包下载 本仓库提供Microsoft Visual C++ 2015 Redistributable x64/x8...

gitblog_09727的博客 3958
上一篇: OVERLAPPED结构
下一篇: 深入浅出VC++串口编程之第三方类
forzy
博客等级 码龄20年 10粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值