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:
Windows solution, query WMI "win32_printer" object:
public static void main(String[] args) {
// select printer that have state = 0 and status = 3, which indicates that printer can print
ProcessBuilder builder = new ProcessBuilder("powershell.exe", "get-wmiobject -class win32_printer | Select-Object Name, PrinterState, PrinterStatus | where {$_.PrinterState -eq 0 -And $_.PrinterStatus -eq 3}");
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);
}
For converting InputStream to String look here: comprehensive StackOverflow answer, or you can simply use:
public static String getStringFromInputStream(InputStream is) {
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
try {
while ((length = is.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
} catch (IOException e1) {
e1.printStackTrace();
}
// StandardCharsets.UTF_8.name() > JDK 7
String finalResult = "";
try {
finalResult = result.toString("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return finalResult;
}
Output:
Name PrinterState PrinterStatus
---- ------------ -------------
Foxit Reader PDF Printer 0 3
Send to OneNote 2010 0 3
Microsoft XPS Document Writer 0 3
Microsoft Print to PDF 0 3
Fax 0 3
\\192.168.50.192\POS_PRINTER 0 3
As you can see, you now have all the printers that are in working state in the string.
You can use your existing method (getAvailablePrinters()) and e.g. add something like this:
ArrayList<String> workingPrinter = new ArrayList<String>();
System.out.println("Working printers:");
for(String printer : getAvailablePrinters()){
if(fullStatus.contains("\n" + printer + " ")){ // add a newline character before the printer name and space after so that it catches exact name
workingPrinter.add(printer);
System.out.println(printer);
}
}
And now you will have a nice list of working printers.
Console output:
Working printers:
Send to OneNote 2010
Foxit Reader PDF Printer
Microsoft XPS Document Writer
Microsoft Print to PDF
Fax
\\192.168.50.192\POS_PRINTER
Of course you have to be careful with the names with this approach - e.g. if "POS_PRINTER" is in all printers but not in working printers list, it could still get added to the workingPrinters list, if there is a working printer named "POS_PRINTER 1" as that name contains "\nPOS_PRINTER " string...