Search code examples
.netwmi-query

WMI query on VolumeChangeEvent for SD card insertion into SD card reader not working


I'm developing an application where I would like to process data automatically from an SD card when it's inserted in an SD card reader. The SD card reader is inserted into the computer and assigned the E: and F: drives and are greyed out when there's no SD card inserted. I've been trying to use an WMI query based on Win32__VolumeChangeEvent or Win32__DeviceChangeEvent, but without success. The error I get for "select * from Win32_VolumeChangeEvent" is invalid class, and "select * from Win32_DeviceChangeEvent" doesn't show me status updates when I insert an SD card into the SD card reader, only for the insertion and removal of the SD card reader itself.

A class that I've been using to experiment is :

 namespace eventTest
{
    class WMIReceiveEvent
    {
        static void Main(string[] args)
        {
            WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
            Console.Read();
        }

        public WMIReceiveEvent()
        {
            try
            {
                ManagementScope scope = new ManagementScope("root\\CIMV2");
                scope.Options.EnablePrivileges = true;
                WqlEventQuery query = new WqlEventQuery("select * from Win32_DeviceChangeEvent");
                ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query);
                Console.WriteLine("Waiting for an event...");

                watcher.EventArrived += new EventArrivedEventHandler(HandleEvent);

                // Start listening for events
                watcher.Start();
            }
            catch (ManagementException err)
            {
                Console.WriteLine("An error occurred while trying to receive an event: " + err.Message);
            }
        }

        private void HandleEvent(object sender,
            EventArrivedEventArgs e)
        {
            Console.WriteLine(e.NewEvent.GetPropertyValue("EventType"));
        }
    }
}

Can anyone provide we with a query that I can use to monitor the arrival of the SD card in Windows or point me out why Win32_VolumeChangeEvent isn't accepted as a valid class and if fixed how it can be used to monitor the arrival of the actual SD card?


Solution

  • The following code is an working solution for my problem, where I am notified when a SD card enters a USB connected SD card reader. The query is

    SELECT * FROM __InstanceOperationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.Size > 0 AND TargetInstance.Description = "Removable disk"
    

    which selects all operations on logical disks where the size is > 0 and where it concerns a removable drive. It is possible to further differentiate between the kind of operation (insert and removal) and to retrieve the drive letter of the inserted SD card. (For examples see this stackoverflow question )

    EDIT: the event that triggers on insertion seems to be an "__InstanceModificationEvent" which can be used instead of the __InstanceOperationEvent (__InstanceModificationEvent is a childclass of __InstanceOperationEvent), in which case the query is:

    SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.Size > 0 AND TargetInstance.Description = "Removable disk"
    

    Complete example:

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Management;
    using System.Threading;
    
    
    namespace eventTest
    {
        class WMIReceiveEvent
        {
            static void Main(string[] args)
            {
                WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
                Console.Read();
            }
    
            public WMIReceiveEvent()
            {
                try
                {
                    ManagementScope scope = new ManagementScope("root\\CIMV2");
                    scope.Options.EnablePrivileges = true;
                    WqlEventQuery query = new WqlEventQuery("SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.Size > 0 AND TargetInstance.Description = \"Removable disk\"");
                    ManagementEventWatcher watcher = new ManagementEventWatcher(scope, query);
                    Console.WriteLine("Waiting for an event...");
    
                    watcher.EventArrived += new EventArrivedEventHandler(HandleEvent);
    
                    // Start listening for events
                    watcher.Start();
                }
                catch (ManagementException err)
                {
                    Console.WriteLine("An error occurred while trying to receive an event: " + err.Message);
                }
            }
    
            private void HandleEvent(object sender,
                EventArrivedEventArgs e)
            {
                //ManagementBaseObject baseObject = (ManagementBaseObject)e.NewEvent;
    
               // if (baseObject.ClassPath.ClassName.Equals("__InstanceCreationEvent"))
                    Console.WriteLine("A drive was connected");
                //else if (baseObject.ClassPath.ClassName.Equals("__InstanceDeletionEvent"))
                    //Console.WriteLine("A drive was removed");
            }
        }
    }