How can i get a printer's make and model in Java?

爷,独闯天下 提交于 2019-11-29 13:22:22
Stephen C

(Cherry-picking some parts of the question that are answerable.)

It seems like it's a know "bug" and I don't really understand the evaluation.

In fact, it is a Request For Enhancement (RFE) not a bug.

The evaluation just indicates that the reviewer thinks he / she has found a way they could implement this on Windows ... if and when they get around to it. It is not a workaround for you.


This related question talks about getting a printer's model using SNMP

You should be able to map this to a solution using a Java SNMP library. This approach assumes that the printer is networked and is SNMP capable ... but I guess you already figured that out.

For those who are interested in this subject, I kept looking for a solution that would use the basic Java libraries but, when I started looking the source code of these libraries, I found out that most of the methods that are supposed to return printer's attributes have never been implemented, they always return a Null value. So, at this moment, there is no way to accomplish this in Java.

There are two workarounds, that I posted on the second edit of my original question:

  • Get these informations via SNMP calls.
  • Use the windows print spooler DLL and retrieve these informations from the driver.

Using JNA, the correct version for OP solution (without duplicated code) is this:

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

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

Basically, it adds PRINTER_INFO_2 support.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!