• 创建作业,并加以限制
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);
}

Windows核心编程笔记之作业的更多相关文章

  1. Windows核心编程笔记之处理字符串

    0x01 ANSI 和宽字符定义 // ANSI 字符定义 CHAR varChar_1 = 'a'; // #typedef char CHAR CHAR varChar_2[] = "A ...

  2. Windows核心编程笔记之进程

    改变进程基址,获取进程基址 #include <Windows.h> #include <iostream> #include <strsafe.h> #inclu ...

  3. Windows核心编程笔记之内核对象

    0x01 子进程继承父进程内核对象句柄 父进程 #include <Windows.h> #include <iostream> #include <strsafe.h& ...

  4. Windows核心编程笔记之错误处理

    0x01 GetLastError() 函数用于获取上一个操作的错误代码 #include <Windows.h> #include <iostream> using name ...

  5. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  6. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  7. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  8. 【Windows】windows核心编程整理(上)

    小续 这是我11年看<windows核心编程>时所作的一些笔记,现整理出来共享给大家 windows核心编程整理(上) windows核心编程整理(下) 线程的基础知识 进程是不活泼的,进 ...

  9. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

随机推荐

  1. JVM-对象及对象内存布局

    目录 前言 类与对象 对象类二分模型 对象 对象内存布局 JOL工具 对象头 Mark Word 类型句柄 对象头与锁膨胀 无锁 偏向锁 轻量级锁 重量级锁 重量级锁降级 实例数据 填充 对象生命周期 ...

  2. 13. Vue CLI脚手架

    一. Vue CLI 介绍 1. 什么是Vue CLI? Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.Vue CLI 致力于将 Vue 生态中的工具基础标准化.它确保了各种构建工 ...

  3. Hibernate在oracle中ID增长的方式

    引用链接:http://blog.csdn.net/w183705952/article/details/7367272 Hibernate在oracle中ID增长的方式 第一种:设置ID的增长策略是 ...

  4. springMVC @InitBinder注解

    springMVC @InitBinder注解.setFieldDefaultPrefix则可以在表单用如user.name进行传递属性

  5. 关于深度学习配置的一些tips

    建立博客的第一天,将以前记录的一些东西存档下,方便查看. 1安装anaconda 2pycharm破解 配置环境变量3虚拟环境推荐是python3.5或3.6版本 4.安装numpy tensorfl ...

  6. 安装JDK9,jemter无法正常启动,怎么退回到JDK8

    安装JDK8,配置环境变量 java -version显示的是8.1 然后安装JDK9之后,java -version显示的是9+8.1 这个时候,无法正常启动jemter 在环境变量中把path的C ...

  7. 关于Java中Collections.sort和Arrays.sort的稳定性问题

    一 问题的提出   关于Java中Collections.sort和Arrays.sort的使用,需要注意的是,在本文中,比较的只有Collections.sort(List<T> ele ...

  8. Java中的IO流 - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...

  9. Python基础之数据类型详解

    为什么会有数据类型? 在介绍具体的数据类型之前,需要了解为什么需要区分数据类型.我们知道,一个公司会有很多个大的部门,每个部门下又会有许多细分的小部门,构成了公司的完整体系结构.如果把python的数 ...

  10. idea报错Selected Java version 11 is not supported by SDK (maximum 8)

    解决方案