当前位置: 首页 > 面试题库 >

如何使用Java获得打印机的品牌和型号?

夏侯浩气
2023-03-14
问题内容

我实际上正在开发一个将打印机共享到服务器的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?bug_id=4673400

看来这是一个已知的“错误”,我不太了解评估。

我在想一种解决方法是通过向打印机发送SNMP请求来获取品牌和型号,但是我对SNMP一无所知,而且我不确定是否有单个SNMP命令来获取品牌和型号。任何打印机。

如果有人对使用Java方法或通过发送SNMP命令或在任何操作系统上可以完成的其他任何操作有想法,那么将非常感谢您的帮助。

编辑:

这是一个已询问相同问题的主题的链接:

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

编辑2:

解决方案:

正如我在评论中说的,我试图通过将OID“
1.3.6.1.2.1.25.3.2.1.3.1”发送给打印机来通过SNMP获取品牌和型号。它似乎可以工作,但是我不确定它是否可以在使用相同OID的任何打印机上工作,并且如果在目标打印机上禁用了SNMP,则可能会崩溃。

因此,我最终选择使用JNA和Winspool.drv获得驱动程序名称。它的一部分已经在JNA中实现,但是我必须添加一些结构和功能。

这是指向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<String> 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<String> 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<String> 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);        
    }

我一直在努力使其最终正常工作,因此我希望这会有所帮助。

如果您要添加的打印后台处理程序API的一些其他功能,在这里你可以找到这个API的引用。

注意:仍然存在一个问题,因为我希望该应用程序为多平台,并且该解决方案仅适用于Windows。 因此,将来我将不得不找到一种解决方案来在Linux
OS和Mac OS X上获得打印机驱动程序的名称。如果有发现,我会及时通知您。


问题答案:

对于那些对此主题感兴趣的人,我一直在寻找一种使用基本Java库的解决方案,但是当我开始查看这些库的源代码时,我发现大多数应该返回打印机属性的方法从来没有实现过,它们总是返回Null值。因此,目前还没有办法用Java来完成。

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

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


 类似资料:
  • 问题内容: 我正在寻找一种获取已安装打印机列表的可能性。我在Windows操作系统上使用JDK 1.6。有人知道解决方案吗? 先感谢您。 问题答案: 只是想添加一些片段:

  • 问题内容: 我想使用PDFBox打印 由iText创建的 PDF文件 。我已经使用PDDocument类及其方法print()成功尝试了此操作。您可以在此处找到文档: http //pdfbox.apache.org/apidocs/。 (我正在使用此代码:) 方法print()很好用,但是 有一个问题:当我需要打印多个文件时,该方法要求我为每个文档选择打印机。 有什么办法只能设置一次打印机吗?

  • 问题内容: 使用Java,我需要在未本地安装的网络打印机上进行打印。我只知道打印机名称。我看过的所有教程都以类似以下内容开始: 问题是可能没有安装打印机,因此在这种情况下服务将为空。我需要直接设置打印机名称,而不仅仅是通过可见的打印机枚举。 问题答案: 如果Java AWT Printing未向运行打印应用程序的Windows / Active Directory用户注册,则无法通过路径找到打印机

  • 我需要发送一个pdf文件打印在一个网络应用程序的服务器端,打印机完全支持pdf打印等,它是网络以及服务器。pdf也存储在服务器上。 我尝试的是点击一个按钮,打印出pdf文件,目前我有以下代码: 但我有几个问题,我如何将pdf放入输入流以打印出来,我可以选择诸如双面打印之类的选项,以及如何从JSF web应用程序中调用它 谢谢

  • 问题内容: 这是Sun教程中的基本打印程序示例: 当显示打印对话框时(第二行),用户可以选择仅打印文档中的页面范围。我能以某种方式获得要打印的页数吗?例如,如果我有一个25页的文档,但是用户选择打印4-10的范围,那么将只打印7页。是否有某种方式可以访问该信息? 我需要它来显示进度条,该进度条随着每打印一页的增加而增加,但是为此,我需要知道将要打印的总页数。 那我怎么得到那个数字呢? 问题答案:

  • 问题内容: Java中有什么方法可以打印到特定的IPP打印机?我发现所有示例代码和教程都集中在如何使用以下类似内容打印特定类型的文档上: 此代码段仅打印到找到的第一台能够打印文档的打印机。就我而言,我想通过其URI查找打印机,但似乎不支持此功能。我尝试使用,而不是,并添加了一个属性,但这不会返回任何打印机。我怀疑查找服务正在寻找可以更改其目标URI的打印机,而不是寻找具有该URI的打印机。 作为最