有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JNA检测音频设备到达/删除

我看到了一些关于这方面的问题,但没有一个对我需要做的事情有帮助

我正在使用JNA来帮助我检测USB设备何时插入/移除

插入/卸下USB驱动器(加密狗)时会收到DBT_DEVICEARRIVALDBT_DEVICEREMOVECOMPLETE事件。但是,当插入/删除音频接口时,不会接收这些事件,只会接收DBT_DEVNODES_CHANGES

DBT_DEVNODES_CHANGES不保存有关设备的任何信息,因为LPRAM始终为0

我想我需要做的是检测这些DBT_DEVNODES_CHANGES事件,并在它们上枚举我的USB设备以识别发生了什么变化?但是如何通过JNA访问所有USB设备呢

到目前为止,我的代码如下(精简):

    package com.company;

    import com.sun.jna.Callback;
    import com.sun.jna.FromNativeContext;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.platform.win32.*;
    import com.sun.jna.win32.StdCallLibrary;
    import com.sun.jna.win32.W32APIOptions;
    import libs.User32;

    import javax.swing.*;

    public class MyForm
    {
        private JPanel top_panel;

        public static final com.sun.jna.platform.win32.Guid.GUID GUID_DEVINTERFACE_USB_DEVICE = new Guid.GUID(new byte[] {
            (byte)0xA5, (byte)0xDC, (byte)0xBF, 0x10, 0x65, 0x30, 0x11, (byte)0xD2, (byte)0x90, 0x1F, 0x00, (byte)0xC0, 0x4F, (byte)0xB9, 0x51, (byte)0xED
        });

        public interface MyUser32 extends User32 
        {
            public static final MyUser32 MYINSTANCE = (MyUser32)      Native.loadLibrary("user32", MyUser32.class, W32APIOptions.UNICODE_OPTIONS);
            public static final int GWLP_WNDPROC = -4;
            public int SetWindowLong(WinDef.HWND hWnd, int nIndex, Callback callback);
            public int RegisterDeviceNotification(WinNT.HANDLE hRecipient, Pointer NotificationFilter, int Flags);
        }

        public interface MyWinUser extends WinUser 
        {        
            public static final int WM_DEVICECHANGE = 0x0219;
            public static final int DBT_DEVICEARRIVAL = 0x8000;
            public static final int DBT_DEVICEREMOVECOMPLETE = 0x8004;
            public static final int DBT_DEVNODES_CHANGED = 0x0007;

        }

        //Create the callback interface
        public interface MyListener extends StdCallLibrary.StdCallCallback 
        {
            public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam);
        }

        public static MyListener listener = new MyListener()
        {
            public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam)
            {
                if (uMsg == MyWinUser.WM_DEVICECHANGE)
                {
                   if(uParam.intValue() == MyWinUser.DBT_DEVICEARRIVAL)
                   {
                       System.out.println("Device was added");
                   }

                   if(uParam.intValue() == MyWinUser.DBT_DEVICEREMOVECOMPLETE)
                   {
                       System.out.println("Device was removed");
                   }

                   if(uParam.intValue() == MyWinUser.DBT_DEVNODES_CHANGED)
                   {                    
                       System.out.println("Device node changed" + lParam.longValue());
                   }
                   return new WinDef.LRESULT(1);
            }
            return new WinDef.LRESULT(0);
        }
    };

    public static void main(String[] args) 
    {
        JFrame frame = new JFrame("MyForm");
        frame.setContentPane(new MyForm().top_panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

        WinDef.HWND hWnd = new WinDef.HWND();
        hWnd.setPointer(Native.getWindowPointer(frame));        
        MyUser32.MYINSTANCE.SetWindowLong(hWnd,MyUser32.GWLP_WNDPROC,listener);


    }
}

编辑:我已开始在收到到达/移除事件后获取设备,并手动检测连接或移除的设备。首先调用SetupDiGetClassDevs工作正常,我能够使用SetupDiEnumDeviceInfo进行迭代。之后,我将调用SetupDienumDeviceInterface,以获取调用SetupDiGetDeviceInterface Detail时所需的SP_设备_接口_数据,这将最终使我能够访问有关设备的供应商、产品等信息

问题是,调用SetupDiEnumDeviceInfo时,我会立即收到一个错误\u NO\u更多\u项

您可以在下面看到我的代码:

    com.sun.jna.Pointer enume =  new Pointer(0);
    WinNT.HANDLE hDevInfo = SetupAPI.INSTANCE.SetupDiGetClassDevs(null,enume,hWnd.getPointer(),SetupAPI.DIGCF_PRESENT | SetupAPI.DIGCF_ALLCLASSES);


    SetupAPI.SP_DEVINFO_DATA spDevInfoData = new SetupAPI.SP_DEVINFO_DATA();
    spDevInfoData.cbSize = spDevInfoData.size();
    int i = 0;
    while(SetupAPI.INSTANCE.SetupDiEnumDeviceInfo(hDevInfo, i, spDevInfoData))
    {
        i++;
        IntByReference requiredSize = null;
        SetupAPI.SP_DEVICE_INTERFACE_DATA  devInterfaceData =  new SetupAPI.SP_DEVICE_INTERFACE_DATA();

        int j = 0;
        while(SetupAPI.INSTANCE.SetupDiEnumDeviceInterfaces(hDevInfo,spDevInfoData.getPointer(),spDevInfoData.InterfaceClassGuid,j,devInterfaceData))
        {
            j++;
            if(Native.getLastError() == ERROR_NO_MORE_ITEMS)
            {
                System.out.println("No more items to enumerate");
            }
        }

        SetupAPI.SP_DEVINFO_DATA deviceInfoData = new SetupAPI.SP_DEVINFO_DATA();
        deviceInfoData.cbSize = deviceInfoData.size();

        boolean test2 = SetupAPI.INSTANCE.SetupDiGetDeviceInterfaceDetail(hDevInfo,devInterfaceData,null,0,requiredSize,deviceInfoData);

        int error = Native.getLastError();
        test2 = true;
    }

共 (1) 个答案

  1. # 1 楼答案

    我无法用当前的实现解决我的问题,但我很幸运地偶然发现了一个实现了我所需要的东西的库。因为我不能简单地发布一个链接(违反规则),所以我在这里发布了完整的类,因为方法与我自己的完全不同,我不能指出代码中帮助我让自己的实现工作的部分

    /* Copyright (c) 2012 Tobias Wolf, All Rights Reserved
    * 
    * This library is free software; you can redistribute it and/or
    * modify it under the terms of the GNU Lesser General Public
    * License as published by the Free Software Foundation; either
    * version 2.1 of the License, or (at your option) any later version.
    * 
    * This library is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    * Lesser General Public License for more details.  
    */
    
    package com.sun.jna.platform.win32;
    
    import com.sun.jna.WString;
    import com.sun.jna.platform.win32.DBT;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_DEVICEINTERFACE;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_HANDLE;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_HDR;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_OEM;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_PORT;
    import com.sun.jna.platform.win32.DBT.DEV_BROADCAST_VOLUME;
    import com.sun.jna.platform.win32.Kernel32;
    import com.sun.jna.platform.win32.User32;
    import com.sun.jna.platform.win32.WinDef.HMODULE;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.platform.win32.WinDef.LPARAM;
    import com.sun.jna.platform.win32.WinDef.LRESULT;
    import com.sun.jna.platform.win32.WinDef.WPARAM;
    import com.sun.jna.platform.win32.WinUser;
    import com.sun.jna.platform.win32.WinUser.HDEVNOTIFY;
    import com.sun.jna.platform.win32.WinUser.MSG;
    import com.sun.jna.platform.win32.WinUser.WNDCLASSEX;
    import com.sun.jna.platform.win32.WinUser.WindowProc;
    import com.sun.jna.platform.win32.Wtsapi32;
    
    // TODO: Auto-generated Javadoc
    /**
    * The Class Win32WindowTest.
    */
    public class Win32WindowDemo implements WindowProc {
    
    /**
     * Instantiates a new win32 window test.
     */
    public Win32WindowDemo() {
        // define new window class
        WString windowClass = new WString("MyWindowClass");
        HMODULE hInst = Kernel32.INSTANCE.GetModuleHandle("");
    
        WNDCLASSEX wClass = new WNDCLASSEX();
        wClass.hInstance = hInst;
        wClass.lpfnWndProc = Win32WindowDemo.this;
        wClass.lpszClassName = windowClass;
    
        // register window class
        User32.INSTANCE.RegisterClassEx(wClass);
        getLastError();
    
        // create new window
        HWND hWnd = User32.INSTANCE
                .CreateWindowEx(
                        User32.WS_EX_TOPMOST,
                        windowClass,
                        "My hidden helper window, used only to catch the windows events",
                        0, 0, 0, 0, 0,
                        null, // WM_DEVICECHANGE contradicts parent=WinUser.HWND_MESSAGE
                        null, hInst, null);
    
        getLastError();
        System.out.println("window sucessfully created! window hwnd: "
                + hWnd.getPointer().toString());
    
        Wtsapi32.INSTANCE.WTSRegisterSessionNotification(hWnd,
                Wtsapi32.NOTIFY_FOR_THIS_SESSION);
    
        /* this filters for all device classes */
        // DEV_BROADCAST_HDR notificationFilter = new DEV_BROADCAST_HDR();
        // notificationFilter.dbch_devicetype = DBT.DBT_DEVTYP_DEVICEINTERFACE;
    
        /* this filters for all usb device classes */
        DEV_BROADCAST_DEVICEINTERFACE notificationFilter = new DEV_BROADCAST_DEVICEINTERFACE();
        notificationFilter.dbcc_size = notificationFilter.size();
        notificationFilter.dbcc_devicetype = DBT.DBT_DEVTYP_DEVICEINTERFACE;
        notificationFilter.dbcc_classguid = DBT.GUID_DEVINTERFACE_USB_DEVICE;
    
        /*
         * use User32.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES instead of
         * DEVICE_NOTIFY_WINDOW_HANDLE to ignore the dbcc_classguid value
         */
        HDEVNOTIFY hDevNotify = User32.INSTANCE.RegisterDeviceNotification(
                hWnd, notificationFilter, User32.DEVICE_NOTIFY_WINDOW_HANDLE);
    
        getLastError();
        if (hDevNotify != null)
            System.out.println("RegisterDeviceNotification was sucessfully!");
    
        MSG msg = new MSG();
        while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) != 0) {
            User32.INSTANCE.TranslateMessage(msg);
            User32.INSTANCE.DispatchMessage(msg);
        }
    
        User32.INSTANCE.UnregisterDeviceNotification(hDevNotify);
        Wtsapi32.INSTANCE.WTSUnRegisterSessionNotification(hWnd);
        User32.INSTANCE.UnregisterClass(windowClass, hInst);
        User32.INSTANCE.DestroyWindow(hWnd);
    
        System.out.println("program exit!");
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see
     * com.sun.jna.platform.win32.User32.WindowProc#callback(com.sun.jna.platform
     * .win32.WinDef.HWND, int, com.sun.jna.platform.win32.WinDef.WPARAM,
     * com.sun.jna.platform.win32.WinDef.LPARAM)
     */
    public LRESULT callback(HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam) {
        switch (uMsg) {
        case WinUser.WM_CREATE: {
            onCreate(wParam, lParam);
            return new LRESULT(0);
        }
        case WinUser.WM_DESTROY: {
            User32.INSTANCE.PostQuitMessage(0);
            return new LRESULT(0);
        }
        case WinUser.WM_SESSION_CHANGE: {
            this.onSessionChange(wParam, lParam);
            return new LRESULT(0);
        }
        case WinUser.WM_DEVICECHANGE: {
            LRESULT lResult = this.onDeviceChange(wParam, lParam);
            return lResult != null ? lResult :
                User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
        default:
            return User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
    }
    
    /**
     * Gets the last error.
     * 
     * @return the last error
     */
    public int getLastError() {
        int rc = Kernel32.INSTANCE.GetLastError();
    
        if (rc != 0)
            System.out.println("error: " + rc);
    
        return rc;
    }
    
    /**
     * On session change.
     * 
     * @param wParam
     *            the w param
     * @param lParam
     *            the l param
     */
    protected void onSessionChange(WPARAM wParam, LPARAM lParam) {
        switch (wParam.intValue()) {
        case Wtsapi32.WTS_CONSOLE_CONNECT: {
            this.onConsoleConnect(lParam.intValue());
            break;
        }
        case Wtsapi32.WTS_CONSOLE_DISCONNECT: {
            this.onConsoleDisconnect(lParam.intValue());
            break;
        }
        case Wtsapi32.WTS_SESSION_LOGON: {
            this.onMachineLogon(lParam.intValue());
            break;
        }
        case Wtsapi32.WTS_SESSION_LOGOFF: {
            this.onMachineLogoff(lParam.intValue());
            break;
        }
        case Wtsapi32.WTS_SESSION_LOCK: {
            this.onMachineLocked(lParam.intValue());
            break;
        }
        case Wtsapi32.WTS_SESSION_UNLOCK: {
            this.onMachineUnlocked(lParam.intValue());
            break;
        }
        }
    }
    
    /**
     * On console connect.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onConsoleConnect(int sessionId) {
        System.out.println("onConsoleConnect: " + sessionId);
    }
    
    /**
     * On console disconnect.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onConsoleDisconnect(int sessionId) {
        System.out.println("onConsoleDisconnect: " + sessionId);
    }
    
    /**
     * On machine locked.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onMachineLocked(int sessionId) {
        System.out.println("onMachineLocked: " + sessionId);
    }
    
    /**
     * On machine unlocked.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onMachineUnlocked(int sessionId) {
        System.out.println("onMachineUnlocked: " + sessionId);
    }
    
    /**
     * On machine logon.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onMachineLogon(int sessionId) {
        System.out.println("onMachineLogon: " + sessionId);
    }
    
    /**
     * On machine logoff.
     * 
     * @param sessionId
     *            the session id
     */
    protected void onMachineLogoff(int sessionId) {
        System.out.println("onMachineLogoff: " + sessionId);
    }
    
    /**
     * On device change.
     * 
     * @param wParam
     *            the w param
     * @param lParam
     *            the l param
     * @return the result. Null if the message is not processed.
     */
    protected LRESULT onDeviceChange(WPARAM wParam, LPARAM lParam) {
        switch (wParam.intValue()) {
        case DBT.DBT_DEVICEARRIVAL: {
            return onDeviceChangeArrival(lParam);
        }
        case DBT.DBT_DEVICEREMOVECOMPLETE: {
            return onDeviceChangeRemoveComplete(lParam);
        }
        case DBT.DBT_DEVNODES_CHANGED: {
            //lParam is 0 for this wParam
            return onDeviceChangeNodesChanged();
        }
        default:
            System.out
                    .println("Message WM_DEVICECHANGE message received, value unhandled.");
        }
        return null;
    }
    
    protected LRESULT onDeviceChangeArrivalOrRemoveComplete(LPARAM lParam, String action) {
        DEV_BROADCAST_HDR bhdr = new DEV_BROADCAST_HDR(lParam.longValue());
        switch (bhdr.dbch_devicetype) {
        case DBT.DBT_DEVTYP_DEVICEINTERFACE: {
            // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363244.aspx
            DEV_BROADCAST_DEVICEINTERFACE bdif = new DEV_BROADCAST_DEVICEINTERFACE(bhdr.getPointer());
            System.out.println("BROADCAST_DEVICEINTERFACE: " + action);
            System.out.println("dbcc_devicetype: " + bdif.dbcc_devicetype);
            System.out.println("dbcc_name: " + bdif.getDbcc_name());
            System.out.println("dbcc_classguid: "
                    + bdif.dbcc_classguid.toGuidString());
            break;
        }
        case DBT.DBT_DEVTYP_HANDLE: {
            // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363245.aspx
            DEV_BROADCAST_HANDLE bhd = new DEV_BROADCAST_HANDLE(bhdr.getPointer());
            System.out.println("BROADCAST_HANDLE: " + action);
            break;
        }
        case DBT.DBT_DEVTYP_OEM: {
            // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363247.aspx
            DEV_BROADCAST_OEM boem = new DEV_BROADCAST_OEM(bhdr.getPointer());
            System.out.println("BROADCAST_OEM: " + action);
            break;
        }
        case DBT.DBT_DEVTYP_PORT: {
            // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363248.aspx
            DEV_BROADCAST_PORT bpt = new DEV_BROADCAST_PORT(bhdr.getPointer());
            System.out.println("BROADCAST_PORT: " + action);
            break;
        }
        case DBT.DBT_DEVTYP_VOLUME: {
            // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363249.aspx
            DEV_BROADCAST_VOLUME bvl = new DEV_BROADCAST_VOLUME(bhdr.getPointer());
            int logicalDriveAffected = bvl.dbcv_unitmask;
            short flag = bvl.dbcv_flags;
            boolean isMediaNotPhysical = 0 != (flag & DBT.DBTF_MEDIA/*value is 1*/);
            boolean isNet = 0 != (flag & DBT.DBTF_NET/*value is 2*/);
            System.out.println(action);
            int driveLetterIndex = 0;
            while (logicalDriveAffected != 0) {
                if (0 != (logicalDriveAffected & 1)) {
                    System.out.println("Logical Drive Letter: " +
                        ((char) ('A' + driveLetterIndex)));
                }
                logicalDriveAffected >>>= 1;
                driveLetterIndex++;
            }
            System.out.println("isMediaNotPhysical:"+isMediaNotPhysical);
            System.out.println("isNet:"+isNet);
            break;
        }
        default:
            return null;
        }
        // return TRUE means processed message for this wParam.
        // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363205.aspx
        // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363208.aspx
        return new LRESULT(1);
    }
    
    protected LRESULT onDeviceChangeArrival(LPARAM lParam) {
        return onDeviceChangeArrivalOrRemoveComplete(lParam, "Arrival");
    }
    
    protected LRESULT onDeviceChangeRemoveComplete(LPARAM lParam) {
        return onDeviceChangeArrivalOrRemoveComplete(lParam, "Remove Complete");
    }
    
    protected LRESULT onDeviceChangeNodesChanged() {
        System.out.println("Message DBT_DEVNODES_CHANGED");
        // return TRUE means processed message for this wParam.
        // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363211.aspx
        return new LRESULT(1);
    }
    
    /**
     * On create.
     * 
     * @param wParam
     *            the w param
     * @param lParam
     *            the l param
     */
    protected void onCreate(WPARAM wParam, LPARAM lParam) {
        System.out.println("onCreate: WM_CREATE");
    }
    
    /**
     * The main method.
     * 
     * @param args
     *            the arguments
     */
    public static void main(String[] args) {
        new Win32WindowDemo();
    }
    }