You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++打印池任务获取问题:JOB_INFO_3字段异常及任务信息查询求助

Answers to Print Queue Enumeration Issues with Non-Existent Printers

Let’s break down each of your questions and walk through practical, actionable solutions tailored to working with non-existent printer queues:


1. Why isn't nextJobId populated in JOB_INFO_3 when calling EnumJobs?

The nextJobId field in JOB_INFO_3 is built for active print servers or functioning physical printers that maintain a linked chain of jobs in their queue. When you send jobs to a non-existent printer, the Windows spooler stores these jobs locally but skips building the full job chain metadata. It only populates essential fields like JobId to track the job for potential retry, but doesn’t waste resources maintaining a linked list when there’s no active printer to process the sequence.

Also, even if you have multiple jobs, requesting only 1 job (the third parameter set to 1) means the spooler has no reason to populate nextJobId—it’s only used when linking to subsequent jobs in a multi-job request.


2. Why aren't JobId fields populated when requesting 3 jobs with EnumJobs?

This is almost certainly a buffer size mismatch. When you pass sizeof(JOB_INFO_3) as the buffer size, you’re only allocating space for one JOB_INFO_3 structure—but you’re asking for 3 jobs. The EnumJobs function will return FALSE in this case, and pcbNeeded will tell you the total bytes required to store all 3 job entries. If you don’t check the return value and just look at the uninitialized buffer, the JobId fields will appear empty or contain garbage data.

A secondary possibility: jobs in a non-existent printer’s queue are often in an error state, which can cause the spooler to restrict full multi-job enumeration—but the buffer size issue is the far more likely culprit here.


3. How to fix failed GetJobA calls for job details?

Let’s troubleshoot this step by step:

  • First, check return values and error codes: After calling GetJobA, run GetLastError() to get specific failure details. Common issues include:

    • ERROR_INSUFFICIENT_BUFFER: sizeof(JOB_INFO_1) is too small. JOB_INFO_1 contains variable-length strings (like pDocument) that are stored in the same buffer. You need to first call GetJobA with a buffer size of 0 to get the required pcbNeeded value, then allocate a buffer of that size and call GetJobA again.
    • ERROR_INVALID_JOB: The JobId you’re using is invalid. Double-check that it came from a successful EnumJobs call (confirm EnumJobs returned TRUE and pcReturned > 0).
    • ERROR_PRINTER_NOT_FOUND: Ensure your hPrinter handle is valid. Even for non-existent printers, OpenPrinterA should return a valid handle if you use the correct printer name and have sufficient access rights (e.g., PRINTER_ACCESS_USE).
  • Example fix code:

    DWORD nbBytes = 0;
    // First call to get required buffer size
    GetJobA(hPrinter, jobId, 1, NULL, 0, &nbBytes);
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        // Handle error
        return;
    }
    // Allocate buffer for job data
    JOB_INFO_1* jobInfo = (JOB_INFO_1*)malloc(nbBytes);
    if (!jobInfo) {
        // Handle allocation failure
        return;
    }
    // Second call to retrieve actual job details
    if (GetJobA(hPrinter, jobId, 1, (LPBYTE)jobInfo, nbBytes, &nbBytes)) {
        // Access jobInfo->pDocument, jobInfo->Status, jobInfo->TotalPages, etc.
    } else {
        // Handle failure, check GetLastError() for specifics
    }
    free(jobInfo);
    

4. Can I retrieve all jobs in a non-existent printer's pool? Yes—here's a reliable workflow

Even for non-existent printers, the Windows spooler retains the job queue, so you can enumerate all jobs with the right approach:

Step-by-Step Solution:

  1. Open a valid printer handle:
    Use OpenPrinterA with your printer’s name and appropriate access rights. Even if the printer doesn’t exist, this will open a handle to the local spool queue.

    HANDLE hPrinter = NULL;
    if (!OpenPrinterA("YourNonExistentPrinterName", &hPrinter, NULL)) {
        // Handle error, check GetLastError()
        return;
    }
    
  2. Get the required buffer size for enumeration:
    Call EnumJobs once with a buffer size of 0 to get pcbNeeded—this tells you how much memory you need to store all job entries. Use JOB_INFO_1 instead of JOB_INFO_3; it’s more reliable for invalid queues and includes all core details (JobId, status, document name, pages, etc.).

    DWORD pcbNeeded = 0, pcReturned = 0;
    EnumJobs(hPrinter, 0, 1, 1, NULL, 0, &pcbNeeded, &pcReturned);
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        // Handle error
        ClosePrinter(hPrinter);
        return;
    }
    
  3. Allocate buffer and enumerate all jobs:
    Allocate the buffer using pcbNeeded, then call EnumJobs again to retrieve all jobs. Request a large enough job count (e.g., 1000) to cover all possible entries in the queue.

    JOB_INFO_1* jobList = (JOB_INFO_1*)malloc(pcbNeeded);
    if (!jobList) {
        ClosePrinter(hPrinter);
        return;
    }
    if (EnumJobs(hPrinter, 0, 1000, 1, (LPBYTE)jobList, pcbNeeded, &pcbNeeded, &pcReturned)) {
        // Iterate over all returned jobs
        for (DWORD i = 0; i < pcReturned; i++) {
            DWORD jobId = jobList[i].JobId;
            LPCSTR docName = jobList[i].pDocument;
            DWORD status = jobList[i].Status;
            // Use GetJobA as shown earlier to fetch more details if needed
        }
    } else {
        // Handle enumeration failure
    }
    
  4. Clean up resources:
    Free the allocated buffer and close the printer handle when you’re done.

    free(jobList);
    ClosePrinter(hPrinter);
    

Key tips:

  • Stick to JOB_INFO_1 or JOB_INFO_2 for non-existent printers—JOB_INFO_3’s linked list functionality doesn’t work well with invalid queues.
  • Always validate return values and check GetLastError() for every spooler API call—this is critical for debugging issues with unresponsive or non-existent printers.

内容的提问来源于stack exchange,提问作者user2274060

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:17:06