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

后端 未结 3 1270
清酒与你
清酒与你 2020-12-20 14:08

I\'m actually working on a Java application that shares printers to a server, and I need this application to get the make and model of the printers it shares.

I know

相关标签:
3条回答
  • 2020-12-20 14:49

    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.
    0 讨论(0)
  • 2020-12-20 14:56

    (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

    • How do i get printer model via snmp in c#?

    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.

    0 讨论(0)
  • 2020-12-20 14:57

    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.

    0 讨论(0)
提交回复
热议问题