не получать __InstanceOperationEvent при отключении или отключении некоторых устройств - PullRequest
2 голосов
/ 27 февраля 2012

Я хочу получить уведомление, когда USB-устройство вставлено / удалено / включено / отключено. Я регистрируюсь в «__InstanceOperationEvent» для Win32_USBControllerDevice .

Проблема в том, что хотя я получаю уведомления о вставке / удалении для всех устройств. Я получаю включенные / отключенные события только для запоминающих устройств USB.

Что я делаю не так?

Заранее спасибо

Ответы [ 2 ]

2 голосов
/ 29 февраля 2012

Немного трудно понять, о чем вы говорите, не предоставив пример кода или не сообщив нам, на каком языке вы работаете.

Класс Win32_USBController является ассоциатором класса Win32_PnPEntity, который имеетЭкземпляр всех USB-устройств независимо от их типа.Таким образом, __InstanceOperationEvent для этого класса ДОЛЖЕН предоставлять уведомления для всех устройств, а не только для запоминающих устройств USB.Точнее, он будет работать для любого PnP-совместимого USB-устройства.

Следующий скрипт - это точка зрения, написанная на VBScript.Он будет уведомлять вас обо всех компонентах USB, когда устройство подключено или отключено.Я тестировал USB-накопители, USB-мышь и клавиатуру и другие устройства, которые у меня были.Все они работали.Я тестировал на Vista x64, но это должно работать с любой версией Windows.

Пример:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colEvents = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 1 " _
        & "Where TargetInstance Isa 'Win32_USBControllerDevice'")

While True
    Set objEvent = colEvents.NextEvent

    Select Case objEvent.Path_.Class
    Case "__InstanceCreationEvent"
        strOutput = "Device inserted:" & vbCr
    Case "__InstanceDeletionEvent"
        strOutput = "Device removed:" & vbCr
    Case Default
        strOutput = objEvent.Path_.Class & vbCr
    End Select

    strDeviceName = objEvent.TargetInstance.Dependent
    strDeviceName = Replace(strDeviceName, Chr(34), "")
    arrDevicePart = Split(strDeviceName, "=")
    strDeviceName = arrDevicePart(1)

    Set colUSBDevices = objWMIService.ExecQuery _
        ("Select * From Win32_PnPEntity Where DeviceID = '" & strDeviceName & "'")
    For Each objUSBDevice in colUSBDevices
        strOutput = strOutput & objUSBDevice.Description & vbCr
    Next

    WScript.Echo strOutput
Wend

Определение, когда устройства включены или отключены, аналогично, ноимеет несколько четких отличий.Вы захотите использовать класс Win32_PnPEntity, который в основном является перечислением всех установленных устройств PnP.Вы должны сосредоточиться на свойстве ConfigManagerErrorCode для каждого экземпляра.Он содержит ту же информацию, что вы найдете в разделе «Состояние устройства» диспетчера устройств.Вы можете понять, почему было бы полезно посмотреть это свойство для любого устройства.Когда устройство меняется, чтобы показать код (0) для нормальной работы, мы можем с уверенностью предположить, что устройство было включено.Когда этот код меняется на код 22, мы знаем, что устройства были отключены.(Все остальные коды обозначают состояния ошибок.) __InstanceModificationEvent - это хороший выбор для отслеживания изменений в любых экземплярах класса Win32_PnPEntity.

Если вас интересуют возможные коды ошибок, вы можете броситьв операторе WScript.Echo в начале скрипта, где он перечисляет все возможные значения.

Пример:

Const wbemFlagUseAmendedQualifiers = &H20000

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set objPnPEntityClass = objWMIService.Get("Win32_PnPEntity", wbemFlagUseAmendedQualifiers)
arrValues = objPnPEntityClass.properties_("ConfigManagerErrorCode").qualifiers_("values")
valueMap = objPnPEntityClass.properties_("ConfigManagerErrorCode").qualifiers_("valuemap")

WScript.Echo "Gathering Device Manager error codes..."
Set dictErrorCodes = CreateObject("Scripting.Dictionary")
For i = 0 to Ubound(arrValues)
    dictErrorCodes.add valueMap(i), arrValues(i)
    '  0, This device is working properly.
    ' 22, This device is disabled.
Next

Set objPnPEntityClass = Nothing

WScript.Echo "Setting up event notification..."
Set colEvents = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceModificationEvent Within 1 " _
        & "Where TargetInstance Isa 'Win32_PnPEntity'")

WScript.Echo "Waiting..."
While True
    Set objEvent = colEvents.NextEvent
    Set objDevice = objEvent.TargetInstance

    Select Case objDevice.ConfigManagerErrorCode
    Case 0      ' This device is working properly.
        strOutput = objDevice.Caption & " is working properly." & vbCr
    Case 22     ' This device is disabled.
        strOutput = objDevice.Caption & " has been disabled." & vbCr
    Case Default
        strDeviceStatus = arrValues(objDevice.ConfigManagerErrorCode)
        strOutput = "(" & objDevice.Caption & ") " &  strDeviceStatus & vbCr
    End Select

    WScript.Echo strOutput
Wend
1 голос
/ 19 декабря 2013

Win32_PnPEntity действительно работал для моего USB-сканера отпечатков пальцев. Но Он не выбирает события устройств, драйвер которых не установлен. Я даю свой код, может быть, с моим кодом возникли проблемы.

static void Main(string[] args)
    {
        WqlEventQuery weqQuery = new WqlEventQuery();
        weqQuery.EventClassName = "__InstanceOperationEvent";
        weqQuery.WithinInterval = new TimeSpan(0, 0, 3);
        weqQuery.Condition = @"TargetInstance ISA 'Win32_PnPEntity'";

        ManagementEventWatcher m_mewWatcher = new ManagementEventWatcher(weqQuery);
        m_mewWatcher.EventArrived += new EventArrivedEventHandler(m_mewWatcher_EventArrived);

        m_mewWatcher.Start();
        m_mewWatcher1.Start();
        Console.ReadLine();
    }
    static void m_mewWatcher_EventArrived(object sender, EventArrivedEventArgs e)
    {

        bool bUSBEvent = false;

        foreach (PropertyData pdData in e.NewEvent.Properties)
        {
            try
            {
                ManagementBaseObject mbo = (ManagementBaseObject)pdData.Value;
                if (mbo != null)
                {
                    foreach (PropertyData pdDataSub in mbo.Properties)
                    {
                        Console.WriteLine("pdDataSub.Name= " + pdDataSub.Name + " and pdDataSub.Value.ToString() = " + (pdDataSub.Value == null ? "" : pdDataSub.Value));
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
    }
...