WEB开发网
开发学院软件开发VC 用Visual C++干干净净地清除进程 阅读

用Visual C++干干净净地清除进程

 2010-08-15 20:47:38 来源:WEB开发网   
核心提示:三、程序代码//#pragma once Process iterator -- iterator over all system processes// Always skips the first (IDLE) process with PID=0.class CProcessIterator { protecte

三、程序代码

//////////////////////////////////////////////////////
#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<string> 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<argc; i++) {
   if (isswitch(argv[i][0])) {
    for (UINT j=1; j<strlen(argv[i]); 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)
"),pid,pid);
    } else {
     fkp.KillProcess(pid, bZap);
    }
   } else if (!bQuiet) {
    tpf(_T("Error: Can't find process '%s'.
"),it->c_str());
   }
  }
  return 0;
}
int help()
{
  tpf(_T("kp: Kill process from command line.
"));
  tpf(_T(" Copyright 2002 Paul DiLascia.
"));
  tpf(_T(" kp [/nqz?] modname1 [modname2....]
"));
  tpf(_T(" where modnameN is a module name; eg foo or foo.exe
"));
  tpf(_T("
"));
  tpf(_T(" /n(othing) don't kill, just show results
"));
  tpf(_T(" /q(uiet) don't show errors
"));
  tpf(_T(" /z(ap) force kill (ignore WM_QUERYENDSESSION)
"));
  tpf(_T("
"));
  return 0;
}

四、小结

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

上一页  1 2 

Tags:Visual 干干净净 清除

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接