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

发表于:2007-05-14来源:作者:点击数: 标签:彻底清除C++visual应用程序进程
三、程序代码 以下是引用片段: /////////////////////////////////////////////////////////////////////////////////////////// #pragmaonce ////////////////// //Processiterator--iteratoroverallsystemprocesses //Alwaysskipsthefirst(IDLE)processwi

  三、程序代码

以下是引用片段:
  ///////////////////////////////////////////////////////////////////////////////////////////
  #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下进程的控制也是有借鉴意义的。

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)