How to check in java if the PC is connected to the network printer?
Asked Answered
E

6

9

Basically, I need to check the status of the n/w printer, if its on or not. Is there any way to do this in java?

Is there any third party API or tool for this?

I tried using PrintServiceLookup in java, but it does not give the status, if its on or not.

Also, if its not possible in java, is there any command that can be run in windows that will give the status of the printer?

Then I can run this command in java and check.

Exenterate answered 14/10, 2015 at 3:58 Comment(6)
Have you tried checking the PrinterIsAcceptingJobs attribute on the PrintService?Oquendo
Yes, It always says printer-is-accepting-jobs : accepting-jobs, even if the printer is not connected to the PC.Exenterate
Does printer have network API? Can you connect to it via http protocol and perform queries which you need? It's just a guess, I haven't done this before.Cantara
do you have the IP of network printer known beforehand???Vindicable
I have the printer IP. But it could be even a USB printer.Exenterate
check the answer provided in the following postAndrosterone
I
4

According to "How Network Printing Works" it really depends on the type of printer and the protocol which it supports. If you know the ip and the port used by you printer and if your printer supports SNMP (just to pick a protocol) you can use the SNMP protocoll to query your printer for information. There is the Java lib SNMP4j which can help you achive this. I would suggest to not use it unless the printer, the ip and the port will never (!) change for your setup. This is because you can run into several problems

  • How to discover an unknown printer ?
  • How to discover the port used by the printer ?
  • How to discover the protocoll used by the printer ?

Lets assume the questions above wouldn't be much of a problem and lets assume every printer would support SNMP. How to get informations out of it ? Besides using the mentioned java lib, you can use snmpget in linux from an terminal. The syntax is as follows:

snmpget -v1 -c public host-ip OID

The OID is an object identifier for every property of you printer reaching from pagecount to toner-cardridge information. If you don't add an OID you'll get the whole list of available OID's. The crux of the matter is although all OID's are standardized the usage of the OID's differ from brand to brand and from printer-model to printer-model. For my HP the following works:

snmpget -v1 -c public 192.168.1.10 iso.3.6.1.2.1.43.17.6.1.5.1.2

and returns

iso.3.6.1.2.1.43.17.6.1.5.1.2 = STRING: "Ready"

the use OID returns the status of the printer for my HP. But if I use the same OID on my Canon I'll get

Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: iso.3.6.1.2.1.43.17.6.1.5.1.2

Therefore it is not even SNMP generically applicable, not mentioning the other protocols which are available.

Considering all these information, the easiest way in my opinition is just check if you can establish the connection to the printer on one of the common printer ports via this code

boolean available = false;
try {
    String serverAddress = "192.168.1.10";
    Socket s = new Socket(serverAddress, 9100);
    s.close();
    available = true;
} catch (IOException e) {
    available = false;
}
System.out.println("printer available: " + available);

Of course this only works if you already know the printer ip.

Intrust answered 20/10, 2015 at 12:46 Comment(2)
what is this String "iso.3.6.1.2.1.43.17.6.1.5.1.2"?Exenterate
This is the OID (net-snmp.org/wiki/index.php/OID) every property of your printer (number of pages printed, cardridge status, etc) has its own OID. So if you want to query the printer for something, you first need the OID of the property you want to query for. But unfortuneatly every printer assigns the OID's differently.Intrust
C
2

If you know your printer IP you could use this code to ping it and check if it's accepting jobs.

import java.io.IOException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;

public class PrinterStatus {

    public static void main(String[] args) {

    PrintService printer = PrintServiceLookup.lookupDefaultPrintService();
    AttributeSet att = printer.getAttributes();

    String ip = "0.0.0.0"; // IP Address of your printer
    boolean check = false;

    for (Attribute a : att.toArray()) {
        if (att.get(a.getClass()).toString().equalsIgnoreCase("accepting-jobs")){
            check = true;
        }
    }

    if (check && runSystemCommand(ip)) System.out.println("Printer ready!");
}

public static boolean runSystemCommand(String ip) {

    ProcessBuilder pb = new ProcessBuilder("ping", "-c 1", ip);
    Process p;
    try {
        p = pb.start();
        return p.waitFor() == 0 ? true : false;
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return false;
  }
}

Of course you need to change this code a little to use it in your case. Except native accessing, I don't see better solution.

Clotilda answered 18/10, 2015 at 6:48 Comment(8)
I have tried this before but the accepting-jobs attribute always returns true even if the printer is turned off.Exenterate
Yes, but if you will have IP address, and it will be switched off, you should not be able to ping it.Clotilda
Ok so in cases where I am connected to network and the printer is off. Even in that case it returns that its accepting jobs.Exenterate
but are you able to ping the device then? if yes, it's little weird.Clotilda
No. I cant ping the device when its disconnectedExenterate
So you will now, that if you could ping device it is on, so probably you could try to print.Clotilda
@anything based on ping and accepting-jobs (even the second thing will be always true) you could decide that you could try to print, as your printer is responding to pingClotilda
OK So finally can we say that if I can ping the n/w printer successfully then I can print else I cant? I dont need to check if the printer is out of paper or its out of ink etc.Exenterate
C
1

I don't think Java provide any portable API for you to check the status. Based on your requirement, you may want to check the windows api

https://msdn.microsoft.com/en-us/library/windows/desktop/dd162752(v=vs.85).aspx

call OpenPrinter2() then ClosePrinter() 

with a little of JNI codes this will be trivial, you may also want to consider https://github.com/java-native-access/jna to make the native accessing part of your code easier

Coexecutor answered 18/10, 2015 at 6:0 Comment(0)
F
1

I can't think of an easy way to do this in java (no doubt someone will come up with a single line of code though!). I'm more familiar with C# and, to answer your Windows question, I'd use Microsoft's WMI, specifically Win32_Printer (https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx). An old CodeProject site shows how to test for an offline printer in C# using Win32_Printer (http://www.codeproject.com/Articles/6069/How-to-Check-if-your-Printer-is-Connected-using-C).

It might work in your case because this guy (http://henryranch.net/software/jwmi-query-windows-wmi-from-java/) has produced jWMI which can query the WMI systems in java. I'm not sure how exhaustive it is, but you'd imagine it could access Win32_Printer. It uses VBScript which it executes within java via cmd.exe and obtains values from stdout so I've no idea about speed, but he also talks about using WMIC.exe which might suit you better.

From his blurb, it looks as if your code could be as straight forward as:

String status = getWMIValue("Select [printer name] from Win32_Printer", "PrinterStatus");

where 7 (0x7) is offline.

or

String status = getWMIValue("Select [printer name] from Win32_Printer", "Availability");

where various states can be discerened (such as 0x7 = power off, or 0x8 = off line, etc.)

The queries also allow a "Select * from" syntax so you could loop through the printers if you didn't have a name.

Win32_Printer has a property (Network as Boolean) that allows you to check whether the printer is local or network, and this (http://blogs.technet.com/b/heyscriptingguy/archive/2006/08/14/how-can-i-list-all-the-printers-on-a-remote-computer.aspx) is an old, but interesting, read on testing for a network printer in VBScript.

These solutions are pretty long in the tooth (I believe MI is the most recent version of WMI, for example), but if that jWMI library can work for you, it might be an answer.

Frankie answered 18/10, 2015 at 8:46 Comment(6)
I tried using this. But I always get status = 3 even when PC is disconnected from the n/w. When I stop Printer Spooler service or remove printer device from the PC then I don't get anything in return. I get a blank response.Exenterate
I read somewhere. If you are retrieving PrinterStatus = 3 or PrinterState = 0, the printer driver may not be feeding accurate information into WMI. WMI retrieves the printer information from the spoolsv.exe process. It is possible the printer driver does not report its status to the spooler. In this case, Win32_Printer reports the printer as Idle.Exenterate
Oh man, so some drivers bypass the spooler? I can't think how you'd get their status in that case. I don't know if the Availability property or ExtendedPrinterStatus property of Win32_Printer would fare any better but it might be worth trying them. Failing that, I'm at the end of my knowledge, I'm afraid.Frankie
ExtendedPrinterStatus gives me 2 (0x2) Unknown and the Availability returns nothing.Exenterate
java jWMI "Select * from Win32_Printer where name = 'WorkCentre 5325 PS'" "DriverName". This is what I am trying and it does return driver name = "Xerox WorkCentre 5325 PS'" properly. So, is the driver bypassing spoole r in this case or what?Exenterate
Oh that really is frustrating - so some properties are reliable and others aren't? I bet if you set that printer to print, the PrinterStatus would show it too.Frankie
F
1

there is java api to native printing facility !! check out this class java.awt.Desktop
java2s.com e.g

Fefeal answered 20/10, 2015 at 9:27 Comment(0)
D
-1

i have used

String WorkOffline = getWMIValue("Select * 
from Win32_Printer 
where Name='printer_name'", "WorkOffline");
returns True/False
Discriminator answered 31/10, 2016 at 5:22 Comment(1)
this assumes the OP uses windows; he does not make any assumptions about the operating systemPius

© 2022 - 2024 — McMap. All rights reserved.