查找打印机是否在线并准备好打印
Finding if printer is online and ready to print
以下 4 个问题没有帮助,因此这不是重复问题:
ONE, TWO, THREE, FOUR
我需要找到一种方法来确定我的系统报告的打印机是否可以打印。
打印机页面:
图中打印机"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)"
如何实现?
如果解决方案 Windows-specific 没问题,请尝试 WMI4Java。这是我的情况:
如您所见,我的默认打印机 "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
请注意,对于 Kyocera 打印机,WorkOffline
是 True
。可能这就是您想知道的。
现在稍微修改一下以过滤打印机列表,以便仅显示活动打印机:
WMI4Java
.get()
.properties(Arrays.asList("Name", "WorkOffline"))
.filters(Arrays.asList("$_.WorkOffline -eq 0"))
.getRawWMIObjectOutput(WMIClass.WIN32_PRINTER)
更新:有人问我如何获取活动打印机名称列表。好吧,由于 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]
更新:
我建议直接像这样使用 Powershell,而不是查询 WMI "win32_printer" 对象,它更干净 API :
Get-Printer | where PrinterStatus -like 'Normal' | fl
查看所有打印机和状态:
Get-Printer | fl Name, PrinterStatus
查看所有属性:
Get-Printer | fl
您仍然可以在 Java 中使用 ProcessBuilder,如下所述。
更新前:
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 转换为 String,请看这里:comprehensive Whosebug 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 " 字符串...
以下 4 个问题没有帮助,因此这不是重复问题:
ONE, TWO, THREE, FOUR
我需要找到一种方法来确定我的系统报告的打印机是否可以打印。
打印机页面:
图中打印机"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)"
如何实现?
如果解决方案 Windows-specific 没问题,请尝试 WMI4Java。这是我的情况:
如您所见,我的默认打印机 "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
请注意,对于 Kyocera 打印机,WorkOffline
是 True
。可能这就是您想知道的。
现在稍微修改一下以过滤打印机列表,以便仅显示活动打印机:
WMI4Java
.get()
.properties(Arrays.asList("Name", "WorkOffline"))
.filters(Arrays.asList("$_.WorkOffline -eq 0"))
.getRawWMIObjectOutput(WMIClass.WIN32_PRINTER)
更新:有人问我如何获取活动打印机名称列表。好吧,由于 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]
更新: 我建议直接像这样使用 Powershell,而不是查询 WMI "win32_printer" 对象,它更干净 API :
Get-Printer | where PrinterStatus -like 'Normal' | fl
查看所有打印机和状态:
Get-Printer | fl Name, PrinterStatus
查看所有属性:
Get-Printer | fl
您仍然可以在 Java 中使用 ProcessBuilder,如下所述。
更新前:
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 转换为 String,请看这里:comprehensive Whosebug 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 " 字符串...