10

私は実際にサーバーとプリンターを共有する Java アプリケーションに取り組んでおり、共有するプリンターのメーカーとモデルを取得するには、このアプリケーションが必要です。

この質問が 3 回か 4 回聞かれたことは知っていますが、誰も答えを見つけていないようです。

私はこのコードを試しました:

PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);

        for (PrintService printer : printServices){           
            System.out.println(printer.getDefaultAttributeValue(PrinterMakeAndModel.class));
            System.out.println(printer.getAttribute(PrinterURI.class));
        }

最初の print は常にnull文字列を返し、2 番目の print はNullPointerExceptionを取得します。

いくつかの調査により、このページにたどり着きました: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4673400

既知の「バグ」のようで、評価がよくわかりません。

回避策として、プリンターに SNMP 要求を送信してメーカーとモデルを取得することを考えていますが、SNMP については何も知りません。また、メーカーとモデルを取得するための単一の SNMP コマンドがあるかどうかもわかりません。任意のプリンターの。

Javaメソッドを使用するか、SNMPコマンドを送信するか、任意のOSで実行できるその他の方法でこれを達成する方法について誰かが考えている場合は、助けていただければ幸いです。

編集 :

同じ質問がされているトピックへのリンクを次に示します。

編集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クラスへのリンクを次に示します。

そして、これら 2 つのクラスを個人的に更新したコードを次に示します。

ウィンスプール:

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

    }

実装された 3 つの関数を呼び出し、結果を表示するメイン クラス:

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 でプリンター ドライバー名を取得するための解決策を見つける必要があります。何か見つかったら、お知らせします。

4

3 に答える 3

3

(答えられる質問のいくつかの部分をチェリーピッキングします。)

既知の「バグ」のようで、評価がよくわかりません。

実際、これはバグではなく、拡張要求(RFE)です。

評価は、レビュー担当者がWindowsでこれを実装できる方法を見つけたと考えていることを示しています...彼らがそれに近づいたら。それはあなたにとっての回避策ではありません。


この関連する質問では、SNMPを使用してプリンターのモデルを取得する方法について説明しています。

これは、JavaSNMPライブラリを使用してソリューションにマップできるはずです。このアプローチは、プリンタがネットワーク化されており、SNMPに対応していることを前提としています...しかし、あなたはすでにそれを理解していると思います。

于 2013-03-18T13:05:01.860 に答える
1

このテーマに興味のある方のために、私は基本的な Java ライブラリを使用するソリューションを探し続けましたが、これらのライブラリのソース コードを調べ始めたとき、プリンターの属性を返すはずのメソッドのほとんどが実装されていないため、常に Null 値を返します。そのため、現時点では Java でこれを実現する方法はありません。

元の質問の2番目の編集に投稿した2つの回避策があります。

  • SNMP 呼び出しを介してこれらの情報を取得します。
  • Windows 印刷スプーラー DLL を使用して、ドライバーからこれらの情報を取得します。
于 2013-04-22T12:23:18.800 に答える
0

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

基本的に、PRINTER_INFO_2サポートを追加します。

于 2015-12-16T21:04:30.180 に答える