演示作业限制设置
演示作业限制设置
文章目录
演示作业限制设置
/*
演示作业限制设置
*/
#include"..\\CommonFiles\\CmnHdr.h"
#include "resource.h"
#include "Job.h"
#include<tchar.h>
#include<strsafe.h>
#include<windowsx.h>
HWND g_hwnd; //对话框句柄(被所有的线程访问)
HANDLE g_hIOCP; //用来接受作业通知完成的端口
HANDLE g_hThreadIOCP; //完成端口线程句柄
CJob g_job; //作业对象句柄
//完成端口的CompletionKey
#define COMPKEY_TERMINATE ((UINT_PTR)0)
#define COMPKEY_STATUS ((UINT_PTR)1)
#define COMPKEY_JOBOBJECT ((UINT_PTR)2)
void GetProcessName(DWORD PID, PTSTR szProcessName, size_t cchSize) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (hProcess ==NULL)
{
_tcscpy_s(szProcessName, cchSize, TEXT("???"));
return;
}
//....
//以上函数调用,可用下列函数来替代,因为下列函数可适用各种情况
DWORD dwSize = (DWORD)cchSize;
QueryFullProcessImageName(hProcess, 0, szProcessName, &dwSize);
CloseHandle(hProcess);
}
DWORD WINAPI JobNotify(PVOID) {
TCHAR sz[3000];
BOOL fDone = FALSE;
ULONG_PTR CompKey;//指定出发这个事件的作业对象的句柄
LPOVERLAPPED po;//进程ID
DWORD dwBytesXferred;//等待的事件ID
while (!fDone)
{
GetQueuedCompletionStatus(g_hIOCP, &dwBytesXferred,
&CompKey, &po, INFINITE);
//应用程序关闭,退出线程
fDone = (CompKey == COMPKEY_TERMINATE);
//lpClassName为NULL则查找所有标题与第二个参数匹配的窗口
HWND hwndLB = FindWindow(NULL, TEXT("Job Lab"));
hwndLB = GetDlgItem(hwndLB, IDC_STATUS);
if (CompKey == COMPKEY_JOBOBJECT)
{
_tcscpy_s(sz, _countof(sz), TEXT("--> Notification:"));
PTSTR psz = sz + _tcslen(sz);
switch (dwBytesXferred)
{
//作业对象中活动进程数量达到上限
case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象中活动进程数已达到上限!"));
break;
//作业对象中当前没有活动的进程
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象中当前没有活动进程"));
break;
//作业对象耗尽指定的时间片
case JOB_OBJECT_MSG_END_OF_JOB_TIME: {
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象耗尽指定的时间片"));
}
break;
//作业对象耗尽指定的内存
case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)导致作业对象消耗内存到达到上限!"),szProcessName,po);
}
break;
//新进程加入作业对象
case JOB_OBJECT_MSG_NEW_PROCESS: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)加入作业对象!"), szProcessName, po);
}
break;
//进程正常退出
case JOB_OBJECT_MSG_EXIT_PROCESS: {
TCHAR szProcessName[MAX_PATH];
DWORD dwExitCode = 0;
//注意进程退出了。但其内核对象并没有释放,还可以从内核对象中获取推出吗
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PtrToUlong(po));
if (NULL != hProcess)
{
GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)正常退出,推出码(%d)!"), szProcessName, po, dwExitCode);
}
break;
//进程异常退出
case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
TCHAR szProcessName[MAX_PATH];
DWORD dwExitCode = 0;
//注意进程退出了。但其内核对象并没有释放,还可以从内核对象中获取推出吗
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PtrToUlong(po));
if (NULL != hProcess)
{
GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)异常退出,推出码(%d)!"), szProcessName, po, dwExitCode);
}
break;
//进程耗尽时间片
case JOB_OBJECT_MSG_END_OF_PROCESS_TIME: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程%s(ID-%d)耗尽事件片!"), szProcessName, po);
}
break;
//进程小号内存数量达到上限
case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程%s(ID=%d)小号内存达到上限!"), szProcessName, po);
}
break;
default:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("未知通知:%d"), dwBytesXferred);
}
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
CompKey = 1;//当作业通知到达时,强迫更新状态
}
//更新作业状态
if (CompKey == COMPKEY_STATUS)
{
static int s_nStatusCount = 0;
StringCchPrintf(sz, _countof(sz),
TEXT("-->状态更新(%u)"), s_nStatusCount++);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
//显示作业对象的基本统计信息
JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION jobai;
g_job.QueryBasicAccountingInfo(&jobai);
StringCchPrintf(sz, _countof(sz),
TEXT(