• 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 << " 
       - 作业内进程的基本信息 -  
    " << 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 << " 
       - 作业内进程 IO 信息 -  
    " << 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 << " 
       - 作业内进程列表 -  
    " << endl;
    	for (DWORD i = 0; i < ProcessID->NumberOfProcessIdsInList; i++)
    	{
    		cout << "[*] 作业中第 " << i << " 个进程 ID: " << ProcessID->ProcessIdList[i] << endl;
    	}
    	cout << " 
       - 父进程 -  
    " << 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);
    }
    

    在这里插入图片描述

  • 相关阅读:
    os.path.split()、os.path.realpath()和os.path.join()
    我终于也有了自己的博客网站
    (Bug修复)C#爬虫,让你不再觉得神秘
    DevExpress弹框、右键菜单、Grid的使用
    Linux 宝塔部署 ASP.NET Core 应用
    C#高级特性(反射)
    WPF 的内部世界(Binding)
    WPF 的内部世界(控件与布局)
    Layui事件监听(表单和数据表格)
    (待更新)tensorboard [Fatal error in launcher: Unable to create process using]
  • 原文地址:https://www.cnblogs.com/csnd/p/11800523.html
Copyright © 2020-2023  润新知