清除无用进程:用Visual  C++干干净净地清除进程来源: 发布时间:星期六, 2009年9月12日 浏览:193次 评论:0
读者朋友们可能经常会碰到这样个问题想对某些进行操作时发现这些文件正在被其它使用处于打开状态而且是被独占打开这时是没法对文件进行操作因此要想操作这些文件必须将打开这些文件进程清除掉那么如何干净地清除进程呢?其实在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()时应用会收到这个消息然后准备退出进程此时般都会弹出个确认对话框告诉用户:"要推出了如果要保存修改东西现在是最佳时机想保存吗?"有 3种选择(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()封装了关闭窗口以及终止逻辑它利用CWindowIterator类对象来枚举进程主窗口(可能不止个见"如何获取某个进程主窗口以及创建进程名?")并发送WM_CLOSE到每个窗口然后等待进程死亡它有个布尔型参数用来指示当应用进程不愿意退出时是否执行TerminateProcess()详细细节请参见下载代码 2、编程步骤 1、 启动Visual C6.0生成个控制台应用将该命名为"kp"; 2、 在代码中添加CfindKillProcess、CProcessIterator类定义; 3、 添加代码编译运行 3、代码 ////////////////////////////////////////////////////// #pragma _disibledevent=> CProcessIterator { protected: DWORD* m_pids; // .gif' /> of procssor IDs DWORD m_count; // size of .gif' /> DWORD m_current; // next .gif' /> item public: CProcessIterator; ~CProcessIterator; DWORD First; DWORD Next { m_pids && m_current < m_count ? m_pids[m_current] : 0; } DWORD GetCount { m_count; } }; ////////////////// // Handy to facilitate finding and killing a process by name. CFindKillProcess { public: CFindKillProcess; ~CFindKillProcess; DWORD FindProcess(LPCTSTR lpModname, BOOL bAddExe=TRUE); BOOL KillProcess(DWORD pid, BOOL bZap); }; //////////////////////////////////////////////////////////////////// # "stdafx.h" # "EnumProc.h" // CProcessIterator - Iterates all processes CProcessIterator::CProcessIterator { m_pids = NULL; } CProcessIterator::~CProcessIterator { delete m_pids; } ////////////////// // Get first process: Call EnumProcesses to init .gif' />. Return first _disibledevent=> m_count = 0; DWORD nalloc = 1024; do { delete m_pids; m_pids = DWORD [nalloc]; (EnumProcesses(m_pids, nalloc*(DWORD), &m_count)) { m_count /= (DWORD); m_current = 1; // skip IDLE process } } while (nalloc <= m_count); 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 (hModule) { GetModuleBaseName(itm.GetProcessHandle,hModule, name, _MAX_PATH); sModName = modname; (strcmpi(sModName.c_str,name)0) pid; sModName ".exe"; (bAddExe && strcmpi(sModName.c_str,name)0) pid; } } 0; } ////////////////// // Kill a process cleanly: Close 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); (!bOKToKill) FALSE; // window doesn't want to die: abort PostMessage(hwnd, WM_CLOSE, 0, 0); } // I've closed the windows; now wait for process to die. BOOL bKilled = TRUE; HANDLE hp=OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid); (hp) { (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0) { (bZap) { // didn't die: force kill it zap requested TerminateProcess(hp,0); } { bKilled = FALSE; } } CloseHandle(hp); } bKilled; } ////////////////////////////////////////////////////////////////////////// # "stdafx.h" # "EnumProc.h" # tpf _tprf // to save typing typedef list<> CStringList; // like MFC, but with STL // pre-declare functions help; // check for switch: / or - inline BOOL isswitch(TCHAR c) { cL'/' || cL'-'; } ( 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 ( i=1; i<argc; i) { (isswitch(argv[i][0])) { for (UINT j=1; j<strlen(argv[i]); j) { switch(tolower(argv[i][j])) { '?': help; 0; 'n': bDisplayOnly=TRUE; ; 'q': bQuiet=TRUE; ; 'z': bZap=TRUE; ; default: help; } } } { cmdargs.push_back(argv[i]); // got a non-switch arg: add to list } } (cmdargs.size<=0) help; // Now iterate args (module names), killing each _disibledevent=> CFindKillProcess fkp; DWORD pid = fkp.FindProcess(it->c_str); (pid) { (bDisplayOnly) { tpf(_T("Kill process %d(0x%08x)\n"),pid,pid); } { fkp.KillProcess(pid, bZap); } } (!bQuiet) { tpf(_T("Error: Can't find process '%s'.\n"),it->c_str); } } 0; } 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")); 0; } 4、小结 本例子通过介绍CfindKillProcess类探讨了在Windows2000下彻底消除进程思路方法虽然该只能在Windows2000环境下编译运行但是该思路方法对Windows98下进程控制也是有借鉴意义 0
相关文章读者评论发表评论 |