如何使用JNA(打印机和作业)从WinspoolUtil和Winspool获取JobInfo2?

时间:2018-05-14 02:49:14

标签: java jna

我想我可以使用这样的东西:

for(JOB_INFO_2 ji2: WinspoolUtil.getJobInfo2(phPrinter)){
// ... 

}

使用Winspool.drv获取此类信息的API JNA是here。但它不完整。

例如,我找不到这个方法: WinspoolUtil.getJobInfo2(?) 在哪里“?”是我不知道的事情。

1 个答案:

答案 0 :(得分:1)

JNA提供的WinspoolUtil和其他Windows API映射可以在jna-platform工件中找到。

看起来JNA会为not have提供现成的映射,以获取打印作业的第2级信息。如果您不需要二级结构提供的详细信息,则可以使用WinspoolUtil#getJobInfo1。此函数使用Winspool.drv EnumJobs function,其文档说明了这一点:

  

JOB_INFO_1结构包含一般打印作业信息; JOB_INFO_2结构有更详细的信息。 JOB_INFO_3结构包含有关作业链接方式的信息。

至于如何获取打印机的句柄,您首先需要枚举打印机,然后打开打印机,然后枚举作业

打印机枚举

如果您知道打印机的确切名称,则可以完全跳过此步骤。

打印机的枚举取决于您要查找的打印机的连接方式(本地/远程/域)以及您需要的详细程度(请参阅Remarks)。

  • 如果您只想快速简便地从注册表中获取本地和远程连接的打印机的最少信息(属性,打印机名称,服务器名称),请使用WinspoolUtil.getAllPrinterInfo4()

    < / LI>
  • 如果您想获得所有已连接打印机的详细信息和/或想要查看其状态,您需要使用WinspoolUtil.getAllPrinterInfo2()。请注意,这可能需要一段时间; EnumPrinters的文档说,如果级别为2,它将在每个远程打印机上调用OpenPrinter,它将不得不等待超时告诉打印机可用。

    或者,如果您想要第2级信息但仅需要本地连接的打印机,请使用WinspoolUtil.getPrinterInfo2()

  • 此外,还有getPrinterInfo1(),但JNA似乎只能使用本地打印机 - 我不确定其性能或详细信息与getPrinterInfo4()的比较。

示例:打印注册表中找到的所有打印机的名称

Winspool.PRINTER_INFO_4[] printers = WinspoolUtil.getPrinterInfo4();

System.out.println("Printers:");
for (Winspool.PRINTER_INFO_4 printer : printers) {
    System.out.println("  Name: " + printer.pPrinterName + ", server: " + printer.pServerName);
}

打开打印机

一旦您枚举了打印机并确定了要使用的打印机,就可以使用Winspool#OpenPrinter打开打印机的手柄。如果您没有打印机的权限,此调用可能会失败。

使用打印机时,请务必记得致电Winspool#ClosePrinter

示例:打开打印机的句柄

Winspool.PRINTER_INFO_4[] printers = WinspoolUtil.getPrinterInfo4();
System.out.println("Opening printer \"" + printers[0].pPrinterName + "\".");

WinNT.HANDLEByReference phPrinter = new WinNT.HANDLEByReference();
boolean ok = Winspool.INSTANCE.OpenPrinter(printers[0].pPrinterName, phPrinter, null);
System.out.println("ok = " + ok);
Winspool.INSTANCE.ClosePrinter(phPrinter.getValue());

作业枚举

现在您已拥有打印机的句柄,您可以使用WinspoolUtil#getJobInfo1来获取作业。但是,这只会为您提供一般的打印作业信息,您可以从EnumJobs函数的备注部分阅读。

示例:打印打印机的所有作业

Winspool.PRINTER_INFO_4[] printers = WinspoolUtil.getPrinterInfo4();
// Just an example - get the first printer from the list
Winspool.PRINTER_INFO_4 printer = printers[4];

WinNT.HANDLEByReference phPrinter = new WinNT.HANDLEByReference();
boolean opened = Winspool.INSTANCE.OpenPrinter(
    printer.pPrinterName,
    phPrinter,
    null
);

if (!opened) {
    System.err.printf("Failed to open printer \"%s\"!", printer.pPrinterName);
    return;
}

Winspool.JOB_INFO_1[] jobs = WinspoolUtil.getJobInfo1(phPrinter);
System.out.printf("Printer \"%s\" has %d jobs\n", printer.pPrinterName, jobs.length);
for (Winspool.JOB_INFO_1 job : jobs) {
    System.out.printf(
        "  Document: \"%s\", owner: %s, status: %s, total pages: %d, pages printed: %d ...\n",
        job.pDocument,
        job.pUserName,
        job.pStatus != null ? job.pStatus : job.Status,
        job.TotalPages,
        job.PagesPrinted
    );
}

Winspool.INSTANCE.ClosePrinter(phPrinter.getValue());

此示例为我生成以下输出:

  

打印机“EPSONA78A80(L355系列)”有1个作业

     

文档:“java - 如何使GetLastError可靠地与JNA一起使用? - Stack Overflow”,所有者:pc,状态:0,总页数:1,打印页数:0 ...

最后,Windows API有许多方法可以枚举打印机和作业,具体取决于您需要的信息级别和打印机。 JNA只有一些方法的映射,但我认为如果你真的需要那些2级的工作信息细节,你可以看看source of WinspoolUtil#getJobInfo1EnumJobs的文档来计算它出来了。

此外,如果您对监视特定打印机假脱机中的更改感兴趣,请查看JNA的Github存储库中的"w32printer" example