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

如何使用JNA通过WinspoolUtil和Winspool获取JobInfo2(打印机与作业)

解决JNA获取打印作业信息(WinspoolUtil.getJobInfo2缺失)的问题

我明白你遇到的困扰了——你提到的那个JNA版本的platform模块里,WinspoolUtil确实没有提供getJobInfo2()这个便捷方法,所以得直接调用Winspool的原生API来实现获取JOB_INFO_2格式的打印作业信息。下面是具体的实现步骤和代码示例:

核心思路

要获取JOB_INFO_2结构体的打印作业数据,需要直接调用Windows原生的EnumJobsAPI(JNA已封装该接口)。整体流程是:

  • 打开目标打印机,获取打印机句柄
  • 调用EnumJobs枚举作业,指定级别为2(对应JOB_INFO_2结构体)
  • 解析返回的字节缓冲区为JOB_INFO_2数组
  • 关闭打印机句柄,释放系统资源

代码实现示例

import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.Winspool;
import com.sun.jna.platform.win32.Winspool.JOB_INFO_2;
import com.sun.jna.ptr.IntByReference;

public class PrintJobProcessor {
    public static void main(String[] args) {
        // 替换为你的打印机名称,网络打印机格式为"\\\\服务器名\\打印机名"
        String targetPrinter = "YourLocalPrinterName";
        HANDLE printerHandle = new HANDLE();
        IntByReference bufferSizeNeeded = new IntByReference();
        IntByReference jobCountReturned = new IntByReference();

        try {
            // 第一步:打开打印机获取句柄
            boolean isPrinterOpened = Winspool.INSTANCE.OpenPrinter(targetPrinter, printerHandle, null);
            if (!isPrinterOpened) {
                System.err.println("打开打印机失败,请检查打印机名称是否正确");
                return;
            }

            // 第二步:先调用一次EnumJobs获取所需缓冲区大小
            boolean firstEnumSuccess = Winspool.INSTANCE.EnumJobs(printerHandle, 0, 100, 2, null, 0, bufferSizeNeeded, jobCountReturned);
            if (!firstEnumSuccess && Native.getLastError() != Winspool.ERROR_INSUFFICIENT_BUFFER) {
                System.err.println("查询作业缓冲区大小失败");
                return;
            }

            // 第三步:分配缓冲区并再次调用EnumJobs获取实际作业数据
            byte[] jobBuffer = new byte[bufferSizeNeeded.getValue()];
            boolean secondEnumSuccess = Winspool.INSTANCE.EnumJobs(printerHandle, 0, 100, 2, jobBuffer, jobBuffer.length, bufferSizeNeeded, jobCountReturned);
            if (!secondEnumSuccess) {
                System.err.println("枚举打印作业失败");
                return;
            }

            // 第四步:解析缓冲区为JOB_INFO_2数组并处理
            JOB_INFO_2[] jobInfos = JOB_INFO_2.toArray(jobBuffer, jobCountReturned.getValue());
            for (JOB_INFO_2 job : jobInfos) {
                System.out.println("作业ID: " + job.JobId);
                System.out.println("文档名称: " + job.pDocument);
                System.out.println("提交用户: " + job.pUserName);
                // 可根据需求访问更多字段,比如job.Status(作业状态)、job.TotalPages(总页数)等
                System.out.println("---");
            }
        } finally {
            // 最后:关闭打印机句柄,释放资源
            if (!printerHandle.equals(HANDLE.INVALID_HANDLE_VALUE)) {
                Winspool.INSTANCE.ClosePrinter(printerHandle);
            }
        }
    }
}

关键参数说明

EnumJobs方法的核心参数含义:

  • hPrinter:打开打印机后得到的句柄(HANDLE类型)
  • FirstJob:起始枚举的作业ID,传0表示从第一个作业开始
  • NoJobs:最大枚举作业数,可根据实际场景调整(比如100)
  • Level:指定返回的作业信息结构体级别,传2对应JOB_INFO_2
  • pJob:存储作业数据的缓冲区,第一次调用传null仅获取所需大小
  • cbBuf:缓冲区的字节长度
  • pcbNeeded:返回实际需要的缓冲区大小(第一次调用后赋值)
  • pcReturned:返回实际枚举到的作业数量

注意事项

  • 建议使用较新版本的JNA和JNA Platform库,减少API缺失问题
  • 打印机名称需准确,网络打印机要使用完整的UNC路径格式
  • 必须在finally块中关闭打印机句柄,避免系统资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:31:07