Windows核心编程笔记之作业
- 创建作业,并加以限制
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核心编程笔记之作业的更多相关文章
- Windows核心编程笔记之处理字符串
0x01 ANSI 和宽字符定义 // ANSI 字符定义 CHAR varChar_1 = 'a'; // #typedef char CHAR CHAR varChar_2[] = "A ...
- Windows核心编程笔记之进程
改变进程基址,获取进程基址 #include <Windows.h> #include <iostream> #include <strsafe.h> #inclu ...
- Windows核心编程笔记之内核对象
0x01 子进程继承父进程内核对象句柄 父进程 #include <Windows.h> #include <iostream> #include <strsafe.h& ...
- Windows核心编程笔记之错误处理
0x01 GetLastError() 函数用于获取上一个操作的错误代码 #include <Windows.h> #include <iostream> using name ...
- 《Windows核心编程》读书笔记 上
[C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 【转】《windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
- 【Windows】windows核心编程整理(上)
小续 这是我11年看<windows核心编程>时所作的一些笔记,现整理出来共享给大家 windows核心编程整理(上) windows核心编程整理(下) 线程的基础知识 进程是不活泼的,进 ...
- windows核心编程---第八章 使用内核对象进行线程同步
使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...
随机推荐
- JVM-对象及对象内存布局
目录 前言 类与对象 对象类二分模型 对象 对象内存布局 JOL工具 对象头 Mark Word 类型句柄 对象头与锁膨胀 无锁 偏向锁 轻量级锁 重量级锁 重量级锁降级 实例数据 填充 对象生命周期 ...
- 13. Vue CLI脚手架
一. Vue CLI 介绍 1. 什么是Vue CLI? Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.Vue CLI 致力于将 Vue 生态中的工具基础标准化.它确保了各种构建工 ...
- Hibernate在oracle中ID增长的方式
引用链接:http://blog.csdn.net/w183705952/article/details/7367272 Hibernate在oracle中ID增长的方式 第一种:设置ID的增长策略是 ...
- springMVC @InitBinder注解
springMVC @InitBinder注解.setFieldDefaultPrefix则可以在表单用如user.name进行传递属性
- 关于深度学习配置的一些tips
建立博客的第一天,将以前记录的一些东西存档下,方便查看. 1安装anaconda 2pycharm破解 配置环境变量3虚拟环境推荐是python3.5或3.6版本 4.安装numpy tensorfl ...
- 安装JDK9,jemter无法正常启动,怎么退回到JDK8
安装JDK8,配置环境变量 java -version显示的是8.1 然后安装JDK9之后,java -version显示的是9+8.1 这个时候,无法正常启动jemter 在环境变量中把path的C ...
- 关于Java中Collections.sort和Arrays.sort的稳定性问题
一 问题的提出 关于Java中Collections.sort和Arrays.sort的使用,需要注意的是,在本文中,比较的只有Collections.sort(List<T> ele ...
- Java中的IO流 - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...
- Python基础之数据类型详解
为什么会有数据类型? 在介绍具体的数据类型之前,需要了解为什么需要区分数据类型.我们知道,一个公司会有很多个大的部门,每个部门下又会有许多细分的小部门,构成了公司的完整体系结构.如果把python的数 ...
- idea报错Selected Java version 11 is not supported by SDK (maximum 8)
解决方案