2017-01-21 19 views
3

следующие 4 вопроса не помогло, поэтому это не является дубликатом:Finding, если принтер подключен и готов к печати

ONE, TWO, THREE, FOUR


мне нужно найти способ узнать, доступен ли принтер для отчетов моей системы для печати или нет.

страница Версия:

enter image description here

В картине, принтер "THERMAL" доступен для печати, но "HPRT PPTII-A (USB)" не доступен для печати. Система показывает мне, что, делая не доступный принтер затененных

Используя следующий код, я могу найти все принтеры в системе

public static List<String> getAvailablePrinters() { 
    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE; 
    PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); 

    PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, aset); 
    ArrayList<String> names = new ArrayList<String>(); 
    for (PrintService p : services) { 
     Attribute at = p.getAttribute(PrinterIsAcceptingJobs.class); 
     if (at == PrinterIsAcceptingJobs.ACCEPTING_JOBS) { 
      names.add(p.getName()); 
     } 

    } 
    return names; 
} 

выход:

[HPRT PPTII-A(USB), THERMAL] 

Проблема: этот код показывает все принтеры, которые система когда-либо устанавливала.

Что мне нужно: этот список должен содержать только действительно доступные принтеры для печати. В этом примере он должен показывать только «THERMAL», а не показывать «HPRT PPTII-A (USB)»

Как это можно достичь?

+0

как насчет [этого] (http://stackoverflow.com/questions/1387938/how-to-check-printer-is-connected-or-not-to-your-pc-by-java)? – MaxG

+0

Это не совсем помогает, просто отправьте меня на страницу документов, в которой я не знаю, что делать ... Добавление как проверенный вопрос – MoisesCol

ответ

3

Если все в порядке, это решение зависит от Windows, попробуйте WMI4Java. Вот моя ситуация:

Printers list

Как вы можете видеть, мой принтер по умолчанию «Kyocera Mita FS-1010» неактивен (неактивно), потому что я просто выключил его.

Теперь добавьте это к вашему Maven POM:

<dependency> 
    <groupId>com.profesorfalken</groupId> 
    <artifactId>WMI4Java</artifactId> 
    <version>1.4.2</version> 
</dependency> 

Тогда это так же просто, как это список всех принтеров с их соответствующим статусом:

package de.scrum_master.app; 

import com.profesorfalken.wmi4java.WMI4Java; 
import com.profesorfalken.wmi4java.WMIClass; 

import java.util.Arrays; 

public class Printer { 
    public static void main(String[] args) { 
     System.out.println(
      WMI4Java 
       .get() 
       .properties(Arrays.asList("Name", "WorkOffline")) 
       .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER) 
     ); 
    } 
} 

Журнал консоли выглядит следующим образом:

Name  : WEB.DE Club SmartFax 
WorkOffline : False 

Name  : Send To OneNote 2016 
WorkOffline : False 

Name  : Microsoft XPS Document Writer 
WorkOffline : False 

Name  : Microsoft Print to PDF 
WorkOffline : False 

Name  : Kyocera Mita FS-1010 KX 
WorkOffline : True 

Name  : FreePDF 
WorkOffline : False 

Name  : FinePrint 
WorkOffline : False 

Name  : Fax 
WorkOffline : False 

Обратите внимание, что WorkOffline является True для K принтер yocera. Наверное, это то, что вы хотели узнать.

А теперь немного модификации для того, чтобы отфильтровать список принтеров, с тем, чтобы показывать только активные принтеры:

  WMI4Java 
       .get() 
       .properties(Arrays.asList("Name", "WorkOffline")) 
       .filters(Arrays.asList("$_.WorkOffline -eq 0")) 
       .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER) 

Update: меня спросили, как получить список имен активных принтеров , Ну, это не так просто из-за shortcoming in WMI4Java, для которого я только что подал запрос на тяну.Это заставляет нас анализировать и фильтровать необработанный вывод WMI, но код все еще довольно прост:

package de.scrum_master.app; 

import com.profesorfalken.wmi4java.WMI4Java; 
import com.profesorfalken.wmi4java.WMIClass; 

import java.util.Arrays; 
import java.util.List; 
import java.util.stream.Collectors; 

public class Printer { 
    public static void main(String[] args) { 
     String rawOutput = WMI4Java 
      .get() 
      .properties(Arrays.asList("Name", "WorkOffline")) 
      .filters(Arrays.asList("$_.WorkOffline -eq 0")) 
      .getRawWMIObjectOutput(WMIClass.WIN32_PRINTER); 
     List<String> printers = Arrays.stream(rawOutput.split("(\r?\n)")) 
      .filter(line -> line.startsWith("Name")) 
      .map(line -> line.replaceFirst(".* : ", "")) 
      .sorted() 
      .collect(Collectors.toList()); 
     System.out.println(printers); 
    } 
} 

Выход консоли выглядит следующим образом:

[Fax, FinePrint, FreePDF, Microsoft Print to PDF, Microsoft XPS Document Writer, Send To OneNote 2016, WEB.DE Club SmartFax] 
+0

И как получить список имен активных принтеров? – Kerooker

+0

Интересный вопрос. См. Мой обновленный ответ. – kriegaex

+0

Отлично. Щедрость ваша. К сожалению, это решение для Windows. Решает мою проблему (и, вероятно, op, учитывая, что он спросил в окнах), но может быть недостаточно для будущих пользователей – Kerooker

1

решение Windows, запрос WMI «Win32_Printer» объект :

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

для преобразования InputStream в строку посмотреть здесь: comprehensive StackOverflow answer, или вы можете просто использовать:

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

Выход:

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 

Как вы можете видеть, теперь у вас есть все принтеры, которые находятся в рабочем состоянии в строке.

Вы можете использовать существующий метод (getAvailablePrinters()) и, например, добавьте что-то вроде этого:

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

И теперь у вас будет хороший список рабочих принтеров.

Консоль вывода:

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 

Конечно, вы должны быть осторожны с именами с этим подходом - например, если «POS_PRINTER» присутствует во всех принтерах, но не в рабочем списке принтеров, он все равно может быть добавлен в список рабочих принтеров, если есть рабочий принтер с именем «POS_PRINTER 1», так как это имя содержит строку «\ nPOS_PRINTER» ...