1.列举所有的任务
调用EnumWindows这个函数 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, // callback function LPARAM lParam // application-defined value ); 如: ::EnumWindows((WNDENUMPROC)enumProc,(LPARAM)this);
enumProc就是那个回调函数,真正的操作,都在这个函数里实现 第二个参数,是用户自定义传送的,比如这里,可以是对话框的指针
enumProc的原型是 BOOL CALLBACK CPListDlg::enumProc(HWND hwnd, LPARAM lParam) 如果是类成员函数,必须是static函数,声明如下 BOOL static CALLBACK enumProc(HWND hwnd, LPARAM lParam); 其中,那个HWND hwnd就是窗口句柄
BOOL CALLBACK CPListDlg::enumProc(HWND hwnd, LPARAM lParam) { CPListDlg * pDlg = (CPListDlg *)lParam;
if (hwnd == NULL) { return FALSE; }
if (hwnd == pDlg->m_hWnd) //这是为了不把自己这个程序列出来,呵呵 { return TRUE; }
if (::IsWindow(hwnd) && ::IsWindowVisible(hwnd) && ((GetWindowLong(hwnd, GWL_EXSTYLE)&WS_EX_TOOLWINDOW)!
=WS_EX_TOOLWINDOW) && (GetWindowLong(hwnd, GWL_HWNDPARENT)==0)) { TCHAR szCap[255] = {0}; ::GetWindowText(hwnd, szCap, 255);
if (strlen(szCap) == 0) { return TRUE; } if (lstrcmp(_T("Program Manager"),szCap) == 0) { return TRUE; }
DWord dwProcessID = 0; ::GetWindowThreadProcessId(hwnd,&dwProcessID); TRACE( "id = %d, name = %s/n", dwProcessID, szCap ); } return TRUE;
}
GetWindowThreadProcessId是获取进行的ID的
if (lstrcmp(_T("Program Manager"),szCap) == 0)
是为了区别出Program Manager这个程序,不知道为什么,会列出这个东西来,晕
2.获取窗口的图标
HICON hIcon = NULL; hIcon = (HICON)::GetClassLong(hwnd,GCL_HICONSM);
if(hIcon == NULL) { hIcon = (HICON)::GetClassLong(hwnd,GCL_HICON); }
if(hIcon == NULL) { hIcon = (HICON)::SendMessage(hwnd, WM_GETICON, ICON_SMALL, 0); }
if(hIcon == NULL) { hIcon = (HICON)::SendMessage(hwnd, WM_GETICON, ICON_BIG, 0); }
记得当时做的时候,有这些代码是因为,有些窗口的图标不能获得,用了上述办法以后,才能全部获得
3.判断窗口是否是正常运行还是未响应的 首先定义两个函数指针, typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW)(HWND); typedef BOOL (WINAPI *PROCISHUNGTHREAD)(DWORD);
然后定义 PROCISHUNGAPPWINDOW m_pIsHungAppWindow; PROCISHUNGTHREAD m_pIsHungThread;
定义一个bool型,来判断当前操作系统是否是Windows NT/2000以上 因为不同的操作系统,判断程序是否运行正常的方式是不一样的
BOOL m_bIsNT;
获取版本信息 OSVERSIONINFO osver = {0};
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osver)) { bRetVal = FALSE; }
if(bRetVal == TRUE) { if (osver.dwPlatformId&VER_PLATFORM_WIN32_NT) { m_bIsNT = TRUE; } else { m_bIsNT = FALSE; }
}
获取那两个函数指针 HMODULE hUser32 = ::GetModuleHandle("user32"); if (!hUser32) { bRetVal = FALSE; }
if(bRetVal == TRUE) { m_pIsHungAppWindow = (PROCISHUNGAPPWINDOW) GetProcAddress( hUser32, "IsHungAppWindow" );
m_pIsHungThread = (PROCISHUNGTHREAD) GetProcAddress( hUser32, "IsHungThread" );
if (!m_pIsHungAppWindow && !m_pIsHungThread) { bRetVal = FALSE; }
}
于是判断,窗口是否是正常运行,还是未响应 代码如下
if(m_bIsNT == TRUE) { BOOL bIsHung = m_pIsHungAppWindow(hwnd); if(bIsHung) { //没有响应 } else { //正在运行 } } else { BOOL bIsHung =m_pIsHungThread(GetWindowThreadProcessId(hwnd,NULL)); if(bIsHung) { //没有响应 } else { //正在运行 } }
4.结束任务 ::PostMessage(hwnd,WM_CLOSE,0,0);
不过调用这个,有时候不一定一下能把窗口关了,比如窗口没响应了,就关不了 于是,得继续想办法
::PostMessage(hwnd,WM_CLOSE,0,0); ::Sleep(300); //如果窗口还没有被关,继续想办法 if(::IsWindow(hwnd)) { DWORD dwProcessID = 0; ::GetWindowThreadProcessId(hwnd,&dwProcessID);
if(TerminateApp(dwProcessID,500) != TA_FAILED) { //结束成功了 }
}
TerminateApp是这样的
DWORD WINAPI CPListDlg::TerminateApp( DWORD dwPID, DWORD dwTimeout ) { HANDLE hProc ; DWORD dwRet ; // If we can't open the process with PROCESS_TERMINATE rights, // then we give up immediately. hProc = ::OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID); if(hProc == NULL) { return TA_FAILED ; } // TerminateAppEnum() posts WM_CLOSE to all windows whose PID // matches your process's. EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ; // Wait on the handle. If it signals, great. If it times out, // then you kill it. if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED); else dwRet = TA_SUCCESS_CLEAN ; CloseHandle(hProc) ; return dwRet ;
}
又有一个回调函数
BOOL CALLBACK CPListDlg::TerminateAppEnum( HWND hwnd, LPARAM lParam ) { DWORD dwID ;
::GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam) { ::PostMessage(hwnd, WM_CLOSE, 0, 0) ; }
return TRUE ;
} 原型是 BOOL static CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;