• 创建作业,并加以限制
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. WPF中Popup上的textbox无法切换到中文输入法

    As Marco Zhou has said in the msdn forum (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b ...

  2. golang-Zap和Go Logger日志库

    目录 在Go语言项目中使用Zap日志库 介绍 默认的Go Logger日志库 实现Go Logger 设置Logger 使用Logger Logger的运行 Go Logger的优势和劣势 优势 劣势 ...

  3. [Elementary Mechanics-01]Two masses and a spring

    [Elementary Mechanics Using Python-01] Question 5.28 Two masses and a spring. Two particles of m = 0 ...

  4. WooYun-2016-199433 -phpmyadmin-反序列化-getshell

    文章参考 http://www.mottoin.com/detail/521.html https://www.cnblogs.com/xhds/p/12579425.html 虽然是很老的漏洞,但在 ...

  5. kubernetes生产实践之redis-cluster

    方案一 自定义yaml文件安装redis cluster 背景 在Kubernetes中部署Redis集群面临挑战,因为每个Redis实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色.为此 ...

  6. P1089_津津的储蓄计划(JAVA语言)

    package 顺序与分支; /* * 题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱, 津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄, ...

  7. Azure Front Door(三)启用 Web Application Firewall (WAF) 保护Web 应用程序,拒绝恶意攻击

    一,引言 上一篇我们利用 Azure Front Door 为后端 VM 部署提供流量的负载均衡.因为是演示实例,也没有实际的后端实例代码,只有一个 "Index.html" 的静 ...

  8. warpperspective 透视变化的opencv实现

    warpperspective 透视变化的opencv2.0实现 1st-------2nd | | | | | |3rd-------4th 原始代码              cv::Mat sr ...

  9. 【分布式】SpringCloud(3)--Eureka服务注册与发现

    1.Eureka概述 1.1.什么是Eureka Eureka是Netflix的一个子模块.基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移. 只需要使用服务的标识符,就可以访问到 ...

  10. 使用Amazon Pinpoint对用户行为追踪

    1.前言 最近在做一个项目,我们的后台大数据团队需要了解用户在使用app的时候,都进行了哪些操作,在哪个页面都干了些什么,以及app日活和月活等等,各种数据.总之就是监控用户行为,说好听一点就是发送反 ...