Windows核心编程笔记之作业

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_38924942/article/details/88803914
  • 创建作业,并加以限制
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);
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38924942/article/details/88803914