• 创建作业,并加以限制
HANDLE WINAPI CreateJob()
{
BOOL IsInJob = FALSE; DWORD ErrorCode = NULL;
// 不能将已经在作业中的进程及子进程放入其他作业中,IsProcessInJob 用于判断进程是否在作业中
IsProcessInJob(GetCurrentProcess(), NULL, &IsInJob);
if (IsInJob == TRUE)
{
// 返回错误代码
ErrorCode = GetLastError();
return (HANDLE)ErrorCode;
}
// 创建一个名为 MyProcessJob 的作业
HANDLE MyJob = CreateJobObject(NULL, TEXT("MyProcessJob")); // 限制作业中进程的最大用户时间为 10000,最大优先级为低
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimit = { 0 };
BasicLimit.LimitFlags = JOB_OBJECT_LIMIT_JOB_TIME | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
BasicLimit.PerJobUserTimeLimit.QuadPart = 10000; BasicLimit.PriorityClass = IDLE_PRIORITY_CLASS;
SetInformationJobObject(MyJob, JobObjectBasicLimitInformation, &BasicLimit, sizeof(BasicLimit)); // 阻止作业中的进程调用 ChangeDisplaySettings 和 ExitWindows(Ex) 函数
JOBOBJECT_BASIC_UI_RESTRICTIONS UIBasicLimit = { 0 };
UIBasicLimit.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS;
SetInformationJobObject(MyJob, JobObjectBasicUIRestrictions, &UIBasicLimit, sizeof(UIBasicLimit));
return MyJob;
}
  • 将进程放入作业当中
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
#include <tchar.h>
using namespace std;
HANDLE WINAPI CreateJob();
DWORD WINAPI ProcessTask();
VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode); int main(int argc, char *argv[])
{
ProcessTask();
return 0;
} DWORD WINAPI ProcessTask()
{
// 创建一个作业,并加以限制
HANDLE MyJob = CreateJob();
// 创建一个进程,并且处于等待状态
TCHAR CmdLine[8] = L"CMD.EXE"; STARTUPINFO StartInfo = { sizeof(StartInfo) }; PROCESS_INFORMATION ProcessInfo = { 0 };
CreateProcess(NULL, CmdLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_SUSPENDED, NULL, NULL, &StartInfo, &ProcessInfo);
// 加入作业
AssignProcessToJobObject(MyJob, ProcessInfo.hProcess);
// 执行处于限制状态下的线程,并关闭句柄,任由它执行
ResumeThread(ProcessInfo.hThread); CloseHandle(ProcessInfo.hThread);
// 最后关闭进程句柄和作业句柄
CloseHandle(MyJob); CloseHandle(ProcessInfo.hProcess);
return TRUE;
}

  • 查询作业内进程的相关信息
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
#include <tchar.h>
using namespace std; HANDLE WINAPI CreateJob();
HANDLE WINAPI ProcessTask();
VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode); int main(int argc, char *argv[])
{
// 错误代码手收集
DWORD ErrorCode = NULL;
// 创建一个添加过进程的作业,并加以限制
HANDLE MyJob = ProcessTask(); // 使用 QueryInformationJobObject 查询作业基本信息
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicAccountInfo = { 0 }; DWORD ResSize = NULL;
if (!QueryInformationJobObject(MyJob, JobObjectBasicAccountingInformation, &BasicAccountInfo, sizeof(JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), &ResSize))
{
ErrorCode = GetLastError();
ErrorCodeTransformation(ErrorCode);
return 0;
}
cout << " \n - 作业内进程的基本信息 - \n" << endl;
cout << "[*] 作业关联的所有活动进程的用户模式执行时间总量: " << BasicAccountInfo.TotalUserTime.LowPart / 10000 << endl;
cout << "[*] 作业关联的所有活动进程的内核模式执行时间总量: " << BasicAccountInfo.TotalKernelTime.LowPart / 10000 << endl;
cout << "[*] 作业关联的所有进程的用户模式执行时间总量: " << BasicAccountInfo.ThisPeriodTotalUserTime.LowPart / 10000 << endl;
cout << "[*] 作业关联的所有进程的内核模式执行时间总量: " << BasicAccountInfo.ThisPeriodTotalKernelTime.LowPart / 10000 << endl;
cout << "[*] 作业关联的所有活动进程遇到的页面错误总数: " << BasicAccountInfo.TotalPageFaultCount << endl;
cout << "[*] 作业在其生命周期内关联的进程总数: " << BasicAccountInfo.TotalProcesses << endl;
cout << "[*] 当前与作业关联的进程总数: " << BasicAccountInfo.ActiveProcesses << endl;
cout << "[*] 由于违反限制而终止的进程总数: " << BasicAccountInfo.TotalTerminatedProcesses << endl; // 使用 QueryInformationJobObject 查询作业中所有进程的 IO 信息
JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION IOBasicInfo = { 0 }; ResSize = NULL;
if (!QueryInformationJobObject(MyJob, JobObjectBasicAndIoAccountingInformation, &IOBasicInfo, sizeof(JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION), &ResSize))
{
ErrorCode = GetLastError();
ErrorCodeTransformation(ErrorCode);
return 0;
}
cout << " \n - 作业内进程 IO 信息 - \n" << endl;
cout << "[*] 由作业中的进程读取 IO 的次数: " << IOBasicInfo.IoInfo.ReadOperationCount << endl;
cout << "[*] 由作业中的进程未读取 IO 的次数: " << IOBasicInfo.IoInfo.ReadTransferCount << endl;
cout << "[*] 由作业中的进程写入 IO 的次数: " << IOBasicInfo.IoInfo.WriteOperationCount << endl;
cout << "[*] 由作业中的进程未写入 IO 的次数: " << IOBasicInfo.IoInfo.WriteTransferCount << endl; // 使用 QueryInformationJobObject 查询作业中的进程信息
#define MAX_PROCESS_IDS 10
ResSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (MAX_PROCESS_IDS - 1) * sizeof(DWORD);
// 这里使用 _alloca 开辟栈上的空间,否则会触发栈溢出异常
PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcessID = (PJOBOBJECT_BASIC_PROCESS_ID_LIST)_alloca(ResSize);
ProcessID->NumberOfAssignedProcesses = MAX_PROCESS_IDS;
if (!QueryInformationJobObject(MyJob, JobObjectBasicProcessIdList, ProcessID, ResSize, &ResSize))
{
ErrorCode = GetLastError();
ErrorCodeTransformation(ErrorCode);
return 0;
}
cout << " \n - 作业内进程列表 - \n" << endl;
for (DWORD i = 0; i < ProcessID->NumberOfProcessIdsInList; i++)
{
cout << "[*] 作业中第 " << i << " 个进程 ID: " << ProcessID->ProcessIdList[i] << endl;
}
cout << " \n - 父进程 - \n" << endl;
cout << "[*] 父进程 ID: " << GetProcessId(GetCurrentProcess()) << endl;
// 关闭句柄
CloseHandle(MyJob);
return 0;
}
// 添加进程至作业中
HANDLE WINAPI ProcessTask()
{
// 创建一个作业,并加以限制
HANDLE MyJob = CreateJob();
// 创建一个进程,并且处于等待状态
TCHAR CmdLine[8] = L"CMD.EXE"; STARTUPINFO StartInfo = { sizeof(StartInfo) }; PROCESS_INFORMATION ProcessInfo = { 0 };
CreateProcess(NULL, CmdLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_SUSPENDED, NULL, NULL, &StartInfo, &ProcessInfo);
// 加入作业
AssignProcessToJobObject(MyJob, ProcessInfo.hProcess);
// 执行处于限制状态下的线程
ResumeThread(ProcessInfo.hThread);
// 最后关闭句柄,任由它们执行
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
return MyJob;
}
// 创建一个作业
HANDLE WINAPI CreateJob()
{
BOOL IsInJob = FALSE; DWORD ErrorCode = NULL;
// 不能将已经在作业中的进程及子进程放入其他作业中,IsProcessInJob 用于判断进程是否在作业中
IsProcessInJob(GetCurrentProcess(), NULL, &IsInJob);
if (IsInJob == TRUE)
{
// 返回错误代码
ErrorCode = GetLastError();
return (HANDLE)ErrorCode;
}
// 创建一个名为 MyProcessJob 的作业
HANDLE MyJob = CreateJobObject(NULL, TEXT("MyProcessJob")); // 限制作业中进程的最大用户时间为 10000,最大优先级为低
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimit = { 0 };
BasicLimit.LimitFlags = JOB_OBJECT_LIMIT_JOB_TIME | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
BasicLimit.PerJobUserTimeLimit.QuadPart = 10000; BasicLimit.PriorityClass = IDLE_PRIORITY_CLASS;
SetInformationJobObject(MyJob, JobObjectBasicLimitInformation, &BasicLimit, sizeof(BasicLimit)); // 阻止作业中的进程调用 ChangeDisplaySettings 和 ExitWindows(Ex) 函数
JOBOBJECT_BASIC_UI_RESTRICTIONS UIBasicLimit = { 0 };
UIBasicLimit.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS;
SetInformationJobObject(MyJob, JobObjectBasicUIRestrictions, &UIBasicLimit, sizeof(UIBasicLimit));
return MyJob;
} // 如果返回错误,可调用此函数打印详细错误信息
VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode)
{
LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = ErrorCode;
// 将错误代码转换为错误信息
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL
);
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), TEXT("错误代码 %d : %s"), dw, lpMsgBuf);
// 弹窗显示错误信息
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw);
}

最新文章

  1. 【树莓派】 Failed to fetch http://mirrordirector.raspbian.org/raspbian/pool/main/c/chkconfig/chkconfig_11.4.54.60.1debian1_all.deb Could not resolve &#39;mirrordirector.raspbian.org&#39;
  2. pinyin4j
  3. java基础--动态代理实现与原理详细分析
  4. SpringBoot入门
  5. vue+springboot前后端分离实现单点登录跨域问题处理
  6. ThinkPHP删除栏目(多)
  7. css学习の第五弹—单位和值
  8. JDBC存储和读取二进制数据
  9. Shell中数组的使用
  10. python -- 面向对象-成员
  11. LeetCode(40):组合总和 II
  12. 一波水题 MZOJ 1035: 贝克汉姆
  13. 2018.08.06 bzoj1503: [NOI2004]郁闷的出纳员(非旋treap)
  14. 开源应用框架BitAdminCore:更新日志20180817
  15. cdoj913-握手 【Havel定理】
  16. 远程登录-出现身份验证错误[可能是由于CredSSP加密Oracle修正]
  17. .NET中发送邮件的实现
  18. 高仿JDK动态代理 底层源码实现
  19. 汉诺塔问题hdu 2065——找规律
  20. [LeetCode] Maximum Depth of Binary Tree dfs,深度搜索

热门文章

  1. 【ZeyFraのJavaEE开发小知识03】@DateTimeFomat和@JsonFormat
  2. FreeBSD 虚拟网卡 网桥 路由 映射
  3. ElasticSearch入门篇(保姆级教程)
  4. Java标识符,关键字,保留字三者区分(主要是从官网摘抄)
  5. webpack4.x 从零开始配置vue 项目(一)基础搭建项目
  6. Git Fetch failed解决办法
  7. 关于Handler同步屏障你可能不知道的问题
  8. Java中BO、DAO、DO、DTO、PO、POJO、VO的概念
  9. Git基本操作流程
  10. springBoot高级:自动配置分析,事件监听,启动流程分析,监控,部署