如何在Java中获得打印机的品牌和型号?

我实际上正在开发一个将打印机共享到服务器的Java应用程序,我需要这个应用程序来获取它共享的打印机的品牌和型号。

我知道这个问题被问了三四次,但似乎没有人找到答案。

我试过这段代码:

PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService printer : printServices){ System.out.println(printer.getDefaultAttributeValue(PrinterMakeAndModel.class)); System.out.println(printer.getAttribute(PrinterURI.class)); } 

第一个打印始终返回一个字符串,第二个打印出一个NullPointerException

一些研究引导我访问此页面: http : //bugs.sun.com/bugdatabase/view_bug.do?video_id = 4673400

这似乎是一个知道“错误”,我真的不理解评估。

我想解决方法是通过向打印机发送SNMP请求来获取make和model,但我不知道有关SNMP的事情,我不确定是否有单个SNMP命令来获取make和model任何打印机。

如果有人知道如何实现这一点,无论是通过使用Java方法还是通过发送SNMP命令或任何可在任何操作系统上完成的任何其他操作,您的帮助将不胜感激。

编辑:

以下是指向同一问题的主题的链接:

  • 如何在javax.print中获取打印机的型号?

编辑2:

方案:

正如我在评论中所说,我试图通过将OID“1.3.6.1.2.1.25.3.2.1.3.1”发送到打印机来通过SNMP获取make和model。 它似乎工作,但我不确定它是否适用于使用相同OID的任何打印机,如果在目标打印机上停用SNMP,它可能会崩溃。

所以我最终选择使用JNA和Winspool.drv获取驱动程序名称。 其中一部分已在JNA中实现,但我必须添加一些结构和function。

这是JNA中现有WinspoolUtil.java和Winspool.java类的链接。

以下是我对这两个类的个人更新的代码。

温斯普尔:

 import java.util.Arrays; import java.util.List; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.platform.win32.WinDef.DWORD; import com.sun.jna.platform.win32.WinDef.INT_PTR; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIOptions; public class WinspoolUpdate { public interface WinspoolLib extends StdCallLibrary { WinspoolLib INSTANCE = (WinspoolLib) Native.loadLibrary("Winspool.drv", WinspoolLib.class, W32APIOptions.UNICODE_OPTIONS); boolean EnumPrinters(int Flags, String Name, int Level, Pointer pPrinterEnum, int cbBuf, IntByReference pcbNeeded, IntByReference pcReturned); boolean GetPrinter(HANDLE hPrinter, int Level, Pointer pPrinter, int cbBuf, IntByReference pcbNeeded); boolean OpenPrinter(String pPrinterName, HANDLEByReference phPrinter, Pointer pDefault); public static class PRINTER_INFO_1 extends Structure { public int Flags; public String pDescription; public String pName; public String pComment; protected List getFieldOrder() { return Arrays.asList(new String[] { "Flags", "pDescription", "pName", "pComment" }); } public PRINTER_INFO_1() { } public PRINTER_INFO_1(int size) { super(new Memory(size)); } } public static class PRINTER_INFO_2 extends Structure { public String pServerName; public String pPrinterName; public String pShareName; public String pPortName; public String pDriverName; public String pComment; public String pLocation; public INT_PTR pDevMode; public String pSepFile; public String pPrintProcessor; public String pDatatype; public String pParameters; public INT_PTR pSecurityDescriptor; public int Attributes; public int Priority; public int DefaultPriority; public int StartTime; public int UntilTime; public int Status; public int cJobs; public int AveragePPM; protected List getFieldOrder() { return Arrays.asList(new String[] { "pServerName", "pPrinterName", "pShareName", "pPortName", "pDriverName", "pComment", "pLocation", "pDevMode", "pSepFile", "pPrintProcessor", "pDatatype", "pParameters", "pSecurityDescriptor", "Attributes", "Priority", "DefaultPriority", "StartTime", "UntilTime", "Status", "cJobs", "AveragePPM" }); } public PRINTER_INFO_2() { } public PRINTER_INFO_2(int size) { super(new Memory(size)); } } public static class PRINTER_INFO_4 extends Structure { public String pPrinterName; public String pServerName; public DWORD Attributes; protected List getFieldOrder() { return Arrays.asList(new String[] { "pPrinterName", "pServerName", "Attributes" }); } public PRINTER_INFO_4() { } public PRINTER_INFO_4(int size) { super(new Memory(size)); } } int PRINTER_ENUM_DEFAULT = 0x00000001; int PRINTER_ENUM_LOCAL = 0x00000002; int PRINTER_ENUM_CONNECTIONS = 0x00000004; int PRINTER_ENUM_FAVORITE = 0x00000004; int PRINTER_ENUM_NAME = 0x00000008; int PRINTER_ENUM_REMOTE = 0x00000010; int PRINTER_ENUM_SHARED = 0x00000020; int PRINTER_ENUM_NETWORK = 0x00000040; int PRINTER_ENUM_EXPAND = 0x00004000; int PRINTER_ENUM_CONTAINER = 0x00008000; int PRINTER_ENUM_ICONMASK = 0x00ff0000; int PRINTER_ENUM_ICON1 = 0x00010000; int PRINTER_ENUM_ICON2 = 0x00020000; int PRINTER_ENUM_ICON3 = 0x00040000; int PRINTER_ENUM_ICON4 = 0x00080000; int PRINTER_ENUM_ICON5 = 0x00100000; int PRINTER_ENUM_ICON6 = 0x00200000; int PRINTER_ENUM_ICON7 = 0x00400000; int PRINTER_ENUM_ICON8 = 0x00800000; int PRINTER_ENUM_HIDE = 0x01000000; } } 

WinspoolUtil:

 import Model.WinspoolUpdate.WinspoolLib; import Model.WinspoolUpdate.WinspoolLib.PRINTER_INFO_2; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.Win32Exception; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import com.sun.jna.platform.win32.Winspool.PRINTER_INFO_1; import com.sun.jna.platform.win32.Winspool.PRINTER_INFO_4; import com.sun.jna.ptr.IntByReference; public class WinspoolUtils2 { public static PRINTER_INFO_1[] getPrinterInfo1() { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 1, null, 0, pcbNeeded, pcReturned); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_1[0]; } PRINTER_INFO_1 pPrinterEnum = new PRINTER_INFO_1(pcbNeeded.getValue()); if (!WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 1, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded, pcReturned)) { throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); } pPrinterEnum.read(); return (PRINTER_INFO_1[]) pPrinterEnum.toArray(pcReturned.getValue()); } public static PRINTER_INFO_2[] getPrinterInfo2() { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 2, null, 0, pcbNeeded, pcReturned); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_2[0]; } PRINTER_INFO_2 pPrinterEnum = new PRINTER_INFO_2(pcbNeeded.getValue()); if (!WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 2, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded, pcReturned)) { throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); } pPrinterEnum.read(); return (PRINTER_INFO_2[]) pPrinterEnum.toArray(pcReturned.getValue()); } public static PRINTER_INFO_4[] getPrinterInfo4() { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 4, null, 0, pcbNeeded, pcReturned); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_4[0]; } PRINTER_INFO_4 pPrinterEnum = new PRINTER_INFO_4(pcbNeeded.getValue()); if (!WinspoolLib.INSTANCE.EnumPrinters(WinspoolLib.PRINTER_ENUM_LOCAL, null, 4, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded, pcReturned)) { throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); } pPrinterEnum.read(); return (PRINTER_INFO_4[]) pPrinterEnum.toArray(pcReturned.getValue()); } public static PRINTER_INFO_2 getPrinterInfo2(String printerName) { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); HANDLEByReference pHandle = new HANDLEByReference(); WinspoolLib.INSTANCE.OpenPrinter(printerName, pHandle, null); WinspoolLib.INSTANCE.GetPrinter(pHandle.getValue(), 2, null, 0, pcbNeeded); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_2(); } PRINTER_INFO_2 pinfo2 = new PRINTER_INFO_2(pcbNeeded.getValue()); WinspoolLib.INSTANCE.GetPrinter(pHandle.getValue(), 2, pinfo2.getPointer(), pcbNeeded.getValue(), pcReturned); pinfo2.read(); return (PRINTER_INFO_2) pinfo2; } } 

一个主类调用三个实现的函数并显示结果:

 public static void main(String[] args) { for(PRINTER_INFO_1 printerInfo : WinspoolUtils2.getPrinterInfo1()) { System.out.println(printerInfo.pName + ": " + printerInfo.pDescription); } for(PRINTER_INFO_2 printerInfo : WinspoolUtils2.getPrinterInfo2()) { System.out.println(printerInfo.pPrinterName + ": " + printerInfo.pDriverName); } PRINTER_INFO_2 printerInfo = WinspoolUtils2.getPrinterInfo2("Canon iR-ADV C7000s GX300 V2.0"); System.out.println(printerInfo.pPrinterName + ": " + printerInfo.pDriverName); } 

我有点努力最终让它工作,所以我希望这会有所帮助。

如果要添加print spooler API的其他一些function,可以在此处找到此API的参考。

注意:仍然存在问题,因为我希望此应用程序是多平台的,此解决方案仅适用于Windows。 因此,在未来,我将不得不找到一个解决方案,以便在Linux操作系统和Mac OS X上获取打印机驱动程序名称。如果我发现某些内容,我会告诉您。

(樱桃挑选问题的某些部分是可以回答的。)

这似乎是一个知道“错误”,我真的不理解评估。

事实上,它是一个增强请求(RFE)而不是一个bug。

评估只是表明评论者认为他/她已经找到了一种可以在Windows上实现这一点的方法……如果他们能够解决这个问题。 这不是一个解决方法。


这个相关问题讨论了如何使用SNMP获取打印机的型号

  • 如何在c#中通过snmp获取打印机型号?

您应该能够使用Java SNMP库将其映射到解决方案。 这种方法假设打印机是联网的并且具有SNMPfunction……但我想你已经想到了这一点。

对于那些对这个主题感兴趣的人,我一直在寻找一个可以使用基本Java库的解决方案,但是当我开始查看这些库的源代码时,我发现大多数应该返回打印机属性的方法从未实现过,它们总是返回Null值。 所以,在这个时刻,没有办法在Java中实现这一点。

有两种解决方法,我在原始问题的第二次编辑中发布:

  • 通过SNMP调用获取这些信息。
  • 使用Windows打印后台处理程序DLL并从驱动程序中检索这些信息。

使用JNA,OP解决方案的正确版本(没有重复的代码)是这样的:

WinspoolExt

 import java.util.Arrays; import java.util.List; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.platform.win32.Winspool; import com.sun.jna.platform.win32.WinDef.INT_PTR; import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.W32APIOptions; public interface WinspoolExt extends Winspool { WinspoolExt INSTANCE = (WinspoolExt) Native.loadLibrary("Winspool.drv", WinspoolExt.class, W32APIOptions.UNICODE_OPTIONS); boolean GetPrinter(HANDLE hPrinter, int Level, Pointer pPrinter, int cbBuf, IntByReference pcbNeeded); boolean OpenPrinter(String pPrinterName, HANDLEByReference phPrinter, Pointer pDefault); public static class PRINTER_INFO_2 extends Structure { public String pServerName; public String pPrinterName; public String pShareName; public String pPortName; public String pDriverName; public String pComment; public String pLocation; public INT_PTR pDevMode; public String pSepFile; public String pPrintProcessor; public String pDatatype; public String pParameters; public INT_PTR pSecurityDescriptor; public int Attributes; public int Priority; public int DefaultPriority; public int StartTime; public int UntilTime; public int Status; public int cJobs; public int AveragePPM; protected List getFieldOrder() { return Arrays.asList(new String[] { "pServerName", "pPrinterName", "pShareName", "pPortName", "pDriverName", "pComment", "pLocation", "pDevMode", "pSepFile", "pPrintProcessor", "pDatatype", "pParameters", "pSecurityDescriptor", "Attributes", "Priority", "DefaultPriority", "StartTime", "UntilTime", "Status", "cJobs", "AveragePPM" }); } public PRINTER_INFO_2() { } public PRINTER_INFO_2(int size) { super(new Memory(size)); } } } 

WinspoolUtilExt

 import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.Win32Exception; import com.sun.jna.platform.win32.WinNT.HANDLEByReference; import com.sun.jna.platform.win32.WinspoolUtil; import com.sun.jna.ptr.IntByReference; import WinspoolExt.PRINTER_INFO_2; public class WinspoolUtilExt extends WinspoolUtil { public static PRINTER_INFO_2[] getPrinterInfo2() { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); WinspoolExt.INSTANCE.EnumPrinters(WinspoolExt.PRINTER_ENUM_LOCAL, null, 2, null, 0, pcbNeeded, pcReturned); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_2[0]; } PRINTER_INFO_2 pPrinterEnum = new PRINTER_INFO_2(pcbNeeded.getValue()); if (!WinspoolExt.INSTANCE.EnumPrinters(WinspoolExt.PRINTER_ENUM_LOCAL, null, 2, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded, pcReturned)) { throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); } pPrinterEnum.read(); return (PRINTER_INFO_2[]) pPrinterEnum.toArray(pcReturned.getValue()); } public static PRINTER_INFO_2 getPrinterInfo2(String printerName) { IntByReference pcbNeeded = new IntByReference(); IntByReference pcReturned = new IntByReference(); HANDLEByReference pHandle = new HANDLEByReference(); WinspoolExt.INSTANCE.OpenPrinter(printerName, pHandle, (Pointer) null); WinspoolExt.INSTANCE.GetPrinter(pHandle.getValue(), 2, null, 0, pcbNeeded); if (pcbNeeded.getValue() <= 0) { return new PRINTER_INFO_2(); } PRINTER_INFO_2 pinfo2 = new PRINTER_INFO_2(pcbNeeded.getValue()); WinspoolExt.INSTANCE.GetPrinter(pHandle.getValue(), 2, pinfo2.getPointer(), pcbNeeded.getValue(), pcReturned); pinfo2.read(); return (PRINTER_INFO_2) pinfo2; } } 

基本上,它增加了PRINTER_INFO_2支持。