3

I need to know the Printer Status. I need to control the Printer Status using Java Program. Example

  1. Check the Printer status, weather will it accept the Job or not,
  2. Out of Paper
  3. Printer queue
  4. Toner
  5. and etc..

I know there is a way to check the basic information, such as name, color supported or not. But I can't find any example to check paper, toner, job queue. I like to know if it is possible to using Java API. I found big API for printer function, but they didn't give a simple example how to use it.

Joachim Sauer
  • 278,207
  • 54
  • 523
  • 586
user2255885
  • 327
  • 3
  • 4
  • 13
  • The API is not usually the place to look for introductions or examples in Java. Try [the tutorials](http://docs.oracle.com/javase/tutorial/) instead. In this particular instance, [this one seems relevant](http://docs.oracle.com/javase/tutorial/2d/printing/). – Joachim Sauer Apr 16 '13 at 12:06
  • @Joachim Sauer: Why do you think your example is "relevant" if in fact it does not show the needed PrinterStateReasons ? I have used the Java Printer API before and I did not see it from the tutorials. – Thorsten S. Apr 16 '13 at 12:24
  • 1
    @ThorstenS.: I've not claimed that the information is in there (and I have not checked it), I was just providing the general information that "examples and sample code" are not usually found in the API, but are mostly restricted to the tutorials. That's quite different to the way the .NET documentation works, for example. – Joachim Sauer Apr 16 '13 at 12:43
  • @user2255885: I was unsuccessful to get it running. *But* PLEASE stop nagging people ! – Thorsten S. Apr 18 '13 at 21:33

4 Answers4

4

Have a look at this PrinterStateReason. And also javax.print.

Maximin
  • 1,540
  • 1
  • 11
  • 30
  • Ok, there is a method to do it. +1 – Thorsten S. Apr 16 '13 at 12:02
  • i like to know few examples how to use PrinterStateReason. I'm sorry guys. i post another question regarding this. – user2255885 Apr 16 '13 at 12:08
  • javax only give limited information such as current status,name, color supported, it wont give door is open,media jam, tray empty etc... Only PrinterStateReason provides all this information. but they didn't tell how to use. I'm looking some examples for that – user2255885 Apr 16 '13 at 12:16
  • guys i just found the way to call PrinterStateReason in my program. but i don't how to use PrinterStateReason to giving printer. we can call PrinterStateReason in this way PrinterStateReason pr =PrinterStateReason.OUTPUT_AREA_FULL; I want to check the state of a giving printer is it possible with PrinterStateReason? – user2255885 Apr 17 '13 at 06:27
  • Hi Maximin, I need to conclude unfortunately that either a) I am too dumb or b) the Printing API does not work for my printer. I hope you can falsify me by writing a program which does inform you of a PrinterState. – Thorsten S. Apr 18 '13 at 21:30
  • @ThorstenS. Currently I don't have a printer to check on, will post back soon as I can. – Maximin Apr 20 '13 at 03:41
2

Getting the complete status of a printer is not possible. Printers have a native driver which is able to request services but because there are so many possible printer functionalities, Java only supports a subset of it.

You can actually offer the user to modify the status by calling

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

which shows the native printer dialog. Despite the information in the javax.print API that it is possible to check the printer state, I was not able to do so for my printer !. (Canon).

Code to check:

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");
  }
}

I have tried to get a PrinterReasonsState by willfully opening the case or removing the paper, but I was unsuccessfull. Perhaps someone else can show how it is possible, but so far it seems that the API offers much more functionality which is in reality not available.

Or in short: It does not work, at least not for my printer.

Thorsten S.
  • 3,788
  • 25
  • 41
  • 1
    You should have a look at this [PrinterStateReason](http://docs.oracle.com/javase/6/docs/api/javax/print/package-summary.html) – Maximin Apr 16 '13 at 11:39
  • well, DATA_TRANSFER_COMPLETE, JOB_CANCELED,JOB_COMPLETE, JOB_FAILED,NO_MORE_EVENTS,REQUIRES_ATTENTION for all we are using (PrintJobEvent pje). I like to know do we need to call this before call a print request or it'll work after call the print request and in the requirement said its a silent printer application so i cant used print dialog. – user2255885 Apr 16 '13 at 11:52
  • @ Maximin Im using a PDFbox to print a PDFFile. – user2255885 Apr 16 '13 at 11:56
  • guys i just found the way to call PrinterStateReason in my program. but i don't how to use PrinterStateReason to giving printer. we can call PrinterStateReason in this way PrinterStateReason pr =PrinterStateReason.OUTPUT_AREA_FULL; I want to check the state of a giving printer is it possible with PrinterStateReason – user2255885 Apr 17 '13 at 06:26
  • @ Thorsten S. i try to implement Set errorSet = pje.getPrintJob().getService().getAttribute(PrinterReasons.getClass()).printerStateReasonSet(Severity.WARNING); while i'm typing i didnt get getService(), seam this will support docprinte. but I'm using PDFbox – user2255885 Apr 17 '13 at 11:06
  • @Thorsten S. I used above code. It gave few out put. Such as printer name ,printer status, job status and etc. First time i ran the code with the local network connection. Second time I ran the code with out the network connection. I got both instant same out put. My question how is it possible? because in second situation there is no connectivity between my machine(where i ran the code) and the printer. – user2255885 Apr 22 '13 at 10:24
2

I was told one could check the printer status this way:

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.");
    }
}

Sadly it seems that my printer doesn't have support for printerState so I can't test it.

Fapaz
  • 1,566
  • 1
  • 17
  • 32
0

UPDATE: Instead of querying WMI "win32_printer" object I would recommend using Powershell directly like this, its much cleaner API :

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

To see all the printers and statuses:

Get-Printer | fl Name, PrinterStatus

To see all the attributes:

Get-Printer | fl

You can still use ProcessBuilder in Java as described below.

Before update:

Solution for Windows only. In Windows you can query WMI "win32_printer" class, so you check that the state on OS layer: Win32_Printer class

In Java you can use ProcessBuilder like this to start PowerShell and execute the PS script like this:

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);

After converting the InputStream to String you should get something like that:

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

State and Status should change for various situations (printer turned off, out of paper, cover opened,...).

This should work, but depends on the printer and drivers. I used this with EPSON TM printers with ESDPRT port and I could get information like: no paper, cover open, printer offline/turned off, printer paused.

More comprehensive answer here: - my StackOverflow answer on a similar question.

Rok T.
  • 301
  • 3
  • 7
  • Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – GhostCat Aug 01 '17 at 14:50