【问题标题】:How to access the status of the printer?如何访问打印机的状态?
【发布时间】:2013-04-16 11:21:34
【问题描述】:

我需要知道打印机状态。我需要使用 Java 程序控制打印机状态。 示例

  1. 检查打印机状态,判断它是否接受作业,
  2. 缺纸
  3. 打印机队列
  4. 碳粉
  5. 等等。

我知道有一种方法可以检查基本信息,例如名称、颜色是否支持。但我找不到任何检查纸张、碳粉、作业队列的示例。我想知道是否可以使用 Java API。我找到了打印机功能的大API,但他们没有给出一个简单的例子如何使用它。

【问题讨论】:

  • API 通常不是在 Java 中寻找介绍或示例的地方。请改用the tutorials。在这种特殊情况下,this one seems relevant.
  • @Joachim Sauer:如果您的示例实际上没有显示所需的 PrinterStateReasons,为什么您认为它是“相关的”?我之前使用过 Java Printer API,但在教程中没有看到。
  • @ThorstenS.:我没有声称信息在其中(我也没有检查过),我只是提供通常找不到“示例和示例代码”的一般信息在 API 中,但主要限于教程。例如,这与 .NET 文档的工作方式完全不同。
  • @user2255885:我没有成功运行它。 但是请不要再唠叨别人了!

标签: java printing


【解决方案1】:

看看这个PrinterStateReason。还有javax.print。

【讨论】:

  • 好的,有一个方法可以做到。 +1
  • 我想知道一些如何使用 PrinterStateReason 的例子。对不起,伙计们。我发布了另一个关于此的问题。
  • javax 只提供有限的信息,例如当前状态、名称、支持的颜色,它不会提供门打开、卡纸、托盘空等...只有 PrinterStateReason 提供所有这些信息。但他们没有告诉如何使用。我正在寻找一些例子
  • 伙计们,我刚刚找到了在我的程序中调用 PrinterStateReason 的方法。但我不知道如何使用 PrinterStateReason 给打印机。我们可以这样调用PrinterStateReason PrinterStateReason pr =PrinterStateReason.OUTPUT_AREA_FULL;我想用 PrinterStateReason 检查给定打印机的状态吗?
  • 嗨 Maximin,很遗憾,我需要得出结论,要么 a) 我太笨,要么 b) 打印 API 不适用于我的打印机。我希望你可以通过编写一个通知你 PrinterState 的程序来伪造我。
【解决方案2】:

无法获取打印机的完整状态。打印机有一个能够请求服务的本机驱动程序,但由于有很多可能的打印机功能,Java 只支持它的一个子集。

您实际上可以通过调用为用户提供修改状态

PrinterJob pj = PrinterJob.getPrinterJob();
pj.printDialog()

显示本机打印机对话框。 尽管 javax.print API 中提供了可以检查打印机状态的信息,我无法为我的打印机这样做!。 (佳能)。

要检查的代码:

import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterStateReason;
import javax.print.attribute.standard.PrinterStateReasons;
import javax.print.attribute.standard.Severity;
import javax.print.event.*;
import java.awt.*;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.util.Set;

/**
 * PrintTest
 */
public class PrintTest implements PrintServiceAttributeListener,PrintJobListener,Doc, Printable, PrintJobAttributeListener {

  private static final transient String TEXT = "12345";

  public static void main(String[] args) {
    PrintTest test = new PrintTest();
    test.checkPrinters();
  }

  public void checkPrinters() {
    Thread newThread = new Thread(new Runnable() {
      public void run() {
    PrintService ps = PrinterJob.getPrinterJob().getPrintService();

    DocFlavor[] myFlavors = ps.getSupportedDocFlavors();
    ps.addPrintServiceAttributeListener(PrintTest.this);
    DocPrintJob docJob = ps.createPrintJob();
      docJob.addPrintJobAttributeListener(PrintTest.this, null);
    docJob.addPrintJobListener(PrintTest.this);
    try {
      docJob.print(PrintTest.this,null);
    }
    catch (PrintException e) {
      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }
    } });

    newThread.start();
    /**
    PrintServiceAttributeSet attSet = ps.getAttributes();
    PrinterStateReasons psr = ps.getAttribute(PrinterStateReasons.class);

    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }          */
  }

  public void attributeUpdate(PrintServiceAttributeEvent psae) {
    System.out.println(psae.getAttributes());
  }

  public void printDataTransferCompleted(PrintJobEvent pje) {
    System.out.println("Transfer completed");
  }

  public void printJobCompleted(PrintJobEvent pje) {
    System.out.println("Completed");
  }

  public void printJobFailed(PrintJobEvent pje) {
    System.out.println("Failed");
    PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }
  }

  public void printJobCanceled(PrintJobEvent pje) {
    System.out.println("Canceled");
  }

  public void printJobNoMoreEvents(PrintJobEvent pje) {
    System.out.println("No more events");
  }

  public void printJobRequiresAttention(PrintJobEvent pje) {
    System.out.println("Job requires attention");
    PrinterStateReasons psr = pje.getPrintJob().getPrintService().getAttribute(PrinterStateReasons.class);
    if (psr != null) {
      Set<PrinterStateReason> errors = psr.printerStateReasonSet(Severity.REPORT);
      for (PrinterStateReason reason : errors)
        System.out.printf(" Reason : %s",reason.getName());
      System.out.println();
    }
  }

  public DocFlavor getDocFlavor() {
    return DocFlavor.SERVICE_FORMATTED.PRINTABLE;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public Object getPrintData() throws IOException {
    return this;
  }

  public DocAttributeSet getAttributes() {
    return null;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public Reader getReaderForText() throws IOException {
    return null; //To change body of implemented methods use File | Settings | File Templates.
  }

  public InputStream getStreamForBytes() throws IOException {
    return null;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
    return pageIndex == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;  //To change body of implemented methods use File | Settings | File Templates.
  }

  public void attributeUpdate(PrintJobAttributeEvent pjae) {
    System.out.println("Look out");
  }
}

我试图通过故意打开机箱或取出纸张来获取 PrinterReasonsState,但我没有成功。也许其他人可以展示它是如何实现的,但到目前为止,API 似乎提供了更多实际上不可用的功能。

或者简而言之: 它不起作用,至少对我的打印机不起作用。

【讨论】:

  • 你应该看看这个PrinterStateReason
  • 好吧,DATA_TRANSFER_COMPLETE、JOB_CANCELED、JOB_COMPLETE、JOB_FAILED、NO_MORE_EVENTS、REQUIRES_ATTENTION 用于我们正在使用的所有内容(PrintJobEvent pje)。我想知道我们是否需要在调用打印请求之前调用它,或者它会在调用打印请求后工作,并且在要求中说它是一个静默打印机应用程序,所以我不能使用打印对话框。
  • @Maximin Im 使用 PDFbox 打印 PDFFile。
  • 伙计们,我刚刚找到了在我的程序中调用 PrinterStateReason 的方法。但我不知道如何使用 PrinterStateReason 给打印机。我们可以这样调用PrinterStateReason PrinterStateReason pr =PrinterStateReason.OUTPUT_AREA_FULL;我想检查给定打印机的状态是否可以使用 PrinterStateReason
  • @Thorsten S. 我尝试实现 Set errorSet = pje.getPrintJob().getService().getAttribute(PrinterReasons.getClass()).printerStateReasonSet(Severity.WARNING);当我输入时,我没有得到 getService(),接缝这将支持 docprinte。但我正在使用 PDFbox
【解决方案3】:

有人告诉我可以通过这种方式检查打印机状态:

PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
AttributeSet attributes = printService.getAttributes();
String printerState = attributes.get(PrinterState.class).toString();
String printerStateReason = attributes.get(PrinterStateReason.class).toString();

System.out.println("printerState = " + printerState); // May be IDLE, PROCESSING, STOPPED or UNKNOWN
System.out.println("printerStateReason = " + printerStateReason); // If your printer state returns STOPPED, for example, you can identify the reason 

if (printerState.equals(PrinterState.STOPPED.toString()) {

    if (printerStateReason.equals(PrinterStateReason.TONER_LOW.toString()) {

        System.out.println("Toner level is low.");
    }
}

很遗憾,我的打印机似乎不支持printerState,所以我无法对其进行测试。

【讨论】:

    【解决方案4】:

    更新: 我建议不要像这样直接使用 Powershell,而不是查询 WMI“win32_printer”对象,它的 API 更简洁:

    Get-Printer | where PrinterStatus -like 'Normal' | fl
    

    查看所有打印机和状态:

    Get-Printer | fl Name, PrinterStatus
    

    查看所有属性:

    Get-Printer | fl
    

    您仍然可以在 Java 中使用 ProcessBuilder,如下所述。

    更新前:

    仅适用于 Windows 的解决方案。 在 Windows 中,您可以查询 WMI "win32_printer" 类,因此您可以检查 OS 层的状态:Win32_Printer class

    在 Java 中,您可以像这样使用 ProcessBuilder 来启动 PowerShell 并像这样执行 PS 脚本:

    String printerName = "POS_PRINTER";
    ProcessBuilder builder = new ProcessBuilder("powershell.exe", "get-wmiobject -class win32_printer | Select-Object Name, PrinterState, PrinterStatus | where {$_.Name -eq '"+printerName+"'}");
    
    String fullStatus = null;
    Process reg;
    builder.redirectErrorStream(true);
    try {
        reg = builder.start();
        fullStatus = getStringFromInputStream(reg.getInputStream());
        reg.destroy();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    System.out.print(fullStatus);
    

    将 InputStream 转换为 String 后,您应该会得到类似的结果:

    Name        PrinterState PrinterStatus
    ----        ------------ -------------
    POS_PRINTER            0             3
    

    状态和状态应因各种情况而改变(打印机关闭、缺纸、盖板打开……)。

    这应该可以,但取决于打印机和驱动程序。我将它与带有 ESDPRT 端口的 EPSON TM 打印机一起使用,我可以获得如下信息:无纸、盖板打开、打印机离线/关闭、打印机暂停。

    更全面的答案在这里: - my StackOverflow answer on a similar question.

    【讨论】:

    • 虽然这在理论上可以回答这个问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多