十七
十七
Published on 2025-10-28 / 2 Visits
0
0

windows作业

什么是作业对象?

作业对象是Windows中用于将多个进程作为一个单元进行管理的机制。它允许你对一组进程进行统一的资源管理和控制。

1. 基本作业管理

#include <windows.h>
#include <iostream>

// 创建作业对象
HANDLE CreateJobObjectExample() {
    HANDLE hJob = CreateJobObject(NULL, L"MyJobObject");
    if (hJob == NULL) {
        std::cout << "创建作业对象失败: " << GetLastError() << std::endl;
    }
    return hJob;
}

2. 将进程添加到作业

BOOL AssignProcessToJob(HANDLE hJob, HANDLE hProcess) {
    return AssignProcessToJobObject(hJob, hProcess);
}

3. 设置作业限制

void SetJobLimits(HANDLE hJob) {
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimits = {0};
    
    // 设置基本限制
    jobLimits.BasicLimitInformation.LimitFlags = 
        JOB_OBJECT_LIMIT_ACTIVE_PROCESS |      // 限制活动进程数
        JOB_OBJECT_LIMIT_PROCESS_TIME |        // 限制进程时间
        JOB_OBJECT_LIMIT_WORKINGSET;           // 限制工作集大小
    
    jobLimits.BasicLimitInformation.ActiveProcessLimit = 5;      // 最多5个进程
    jobLimits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = 
        10000000; // 每个进程最多运行1秒(100纳秒单位)
    
    jobLimits.ProcessMemoryLimit = 100 * 1024 * 1024; // 100MB内存限制
    jobLimits.BasicLimitInformation.MinimumWorkingSetSize = 4096;
    jobLimits.BasicLimitInformation.MaximumWorkingSetSize = 16 * 1024 * 1024;
    
    SetInformationJobObject(hJob, 
        JobObjectExtendedLimitInformation, 
        &jobLimits, 
        sizeof(jobLimits));
}

4. 完整的作业管理示例

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>

class JobManager {
private:
    HANDLE m_hJob;
    std::vector<PROCESS_INFORMATION> m_processes;

public:
    JobManager() : m_hJob(NULL) {}
    
    ~JobManager() {
        Cleanup();
    }
    
    bool Initialize(const wchar_t* jobName = nullptr) {
        m_hJob = CreateJobObject(NULL, jobName);
        if (!m_hJob) {
            std::cout << "创建作业对象失败,错误代码: " << GetLastError() << std::endl;
            return false;
        }
        
        // 设置作业在所有进程退出时自动终止
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimits = {0};
        jobLimits.BasicLimitInformation.LimitFlags = 
            JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
        
        if (!SetInformationJobObject(m_hJob, 
            JobObjectExtendedLimitInformation, 
            &jobLimits, 
            sizeof(jobLimits))) {
            std::cout << "设置作业限制失败,错误代码: " << GetLastError() << std::endl;
            CloseHandle(m_hJob);
            m_hJob = NULL;
            return false;
        }
        
        std::cout << "作业对象创建成功!" << std::endl;
        return true;
    }
    
    bool CreateProcessInJob(const wchar_t* processPath, const wchar_t* commandLine = nullptr) {
        STARTUPINFO si = {sizeof(si)};
        PROCESS_INFORMATION pi = {0};
        
        // 构建命令行
        std::wstring fullCommandLine;
        if (commandLine) {
            fullCommandLine = commandLine;
        } else {
            fullCommandLine = processPath;
        }
        
        std::wcout << L"正在创建进程: " << fullCommandLine << std::endl;
        
        if (!CreateProcessW(
            processPath,
            &fullCommandLine[0],
            NULL, NULL, FALSE,
            CREATE_SUSPENDED,
            NULL, NULL, &si, &pi)) {
            
            DWORD error = GetLastError();
            std::cout << "创建进程失败,错误代码: " << error << std::endl;
            
            // 常见错误处理
            if (error == ERROR_FILE_NOT_FOUND) {
                std::cout << "错误: 找不到指定的文件" << std::endl;
            }
            return false;
        }
        
        // 将进程添加到作业
        if (!AssignProcessToJobObject(m_hJob, pi.hProcess)) {
            DWORD error = GetLastError();
            std::cout << "添加到作业失败,错误代码: " << error << std::endl;
            TerminateProcess(pi.hProcess, 1);
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
            return false;
        }
        
        // 恢复进程执行
        ResumeThread(pi.hThread);
        
        std::wcout << L"进程创建成功,PID: " << pi.dwProcessId << std::endl;
        m_processes.push_back(pi);
        return true;
    }
    
    void PrintJobInfo() {
        JOBOBJECT_BASIC_ACCOUNTING_INFORMATION info = {0};
        if (QueryInformationJobObject(m_hJob, 
            JobObjectBasicAccountingInformation, 
            &info, 
            sizeof(info), 
            NULL)) {
            
            std::cout << "=== 作业信息 ===" << std::endl;
            std::cout << "活动进程数: " << info.ActiveProcesses << std::endl;
            std::cout << "总进程数: " << info.TotalProcesses << std::endl;
            std::cout << "=================" << std::endl;
        }
    }
    
    void TerminateAllProcesses() {
        std::cout << "正在终止所有进程..." << std::endl;
        TerminateJobObject(m_hJob, 0);
    }
    
    void WaitForAllProcesses(DWORD timeout = INFINITE) {
        WaitForSingleObject(m_hJob, timeout);
    }
    
    void Cleanup() {
        if (m_hJob) {
            CloseHandle(m_hJob);
            m_hJob = NULL;
        }
        
        for (auto& pi : m_processes) {
            if (pi.hProcess) CloseHandle(pi.hProcess);
            if (pi.hThread) CloseHandle(pi.hThread);
        }
        m_processes.clear();
    }
};

// 改进的使用示例
int main() {
    JobManager jobMgr;
    
    if (jobMgr.Initialize(L"ExampleJob")) {
        
        // 在作业中创建进程 - 使用完整路径
        jobMgr.CreateProcessInJob(L"C:\\Windows\\System32\\notepad.exe");
        jobMgr.CreateProcessInJob(L"C:\\Windows\\System32\\calc.exe");
        
        // 显示作业信息
        jobMgr.PrintJobInfo();
        
        std::cout << "进程已启动,请检查任务管理器中的notepad和calculator进程" << std::endl;
        std::cout << "按回车键终止所有进程并退出..." << std::endl;
        
        // 确保输入被正确读取
        std::cin.clear();
        std::cin.get();
        
        std::cout << "正在清理..." << std::endl;
        jobMgr.TerminateAllProcesses();
        jobMgr.WaitForAllProcesses(3000);
        
        std::cout << "程序结束" << std::endl;
    } else {
        std::cout << "初始化失败,程序退出" << std::endl;
        return 1;
    }
    
    return 0;
}

重要规则

  • 进程只能属于一个作业

  • 一旦分配,无法移除

  • 子进程自动继承父进程的作业


Comment