Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# usb detection

Tags:

c#

.net

usb

We have several processes in the current Application. One process handles about detection and removel of USB loader. The code to handle detection and removal as below.

protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_DEVICECHANGE: OnDeviceChange(ref m);
                    break;
            }
            base.WndProc(ref m);
        }

private void OnDeviceChange(ref Message msg)
        {
            int wParam = (int)msg.WParam;
            Win32.DEV_BROADCAST_VOLUME dbVol = new Win32.DEV_BROADCAST_VOLUME();
            Win32.DEV_BROADCAST_HDR msgDevHeader = new Win32.DEV_BROADCAST_HDR();
            const int DBT_DEVTYP_VOLUME = 0x00000002;
            string loaderUpdates;

            switch (wParam)
            {
                case Win32.DBT_DEVICEARRIVAL:
                    int devType = Marshal.ReadInt32(msg.LParam, 4);

                    if (devType == DBT_DEVTYP_VOLUME)
                    {
                    }
                    break;

                case Win32.DBT_DEVICEREMOVECOMPLETE:

                                     break;
            }
        }

When i run the process which handles USB loader in the debug mode in the visual studio environment, it detects USB properly.but still i receive multiple messages. receives message with wparam value as "7" 3 times and then receives wparam value as "32768(0x8000/DBT_DEVICEARRIVAL )". Is it normal?

When i run all the other process along with the process which detects USB,it seems to be always the message with wparam value as "7" only received. receives meesage with wparam as "7" 5 times. There is no message with wparam values as "(0x8000/DBT_DEVICEARRIVAL )". what could be the problem?

Appreciate any inputs/solutions.

Regards Raju

like image 948
user209293 Avatar asked Mar 30 '11 22:03

user209293


1 Answers

From what I've seen, that's normal. I run into exactly the same issue here.

Two things you can do - set a var for DateTime.Now and then check on the next arrival to see if time difference between the arrivals is less than x seconds from the last time there was an event (basically store the time from when you last handled an arrival)

or

You can store the list of drives and if the event handles the same device as you already have, then you ignore it.

But yes, because USB devices often present themselves to the system as multiple devices, it tends to send multiple device insertions.

Another thing I've used to get around this is using WMI's events, with a watcher to detect logical storage events (__InstanceCreation with a target of Win32_LogicalDisk)

    private void startMonitor()
    {
        while (serviceStarted)
        {
            ManagementEventWatcher watcher = new ManagementEventWatcher();

            WqlEventQuery query = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_LogicalDisk'");

            watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
            watcher.Query = query;
            watcher.Start();
            watcher.WaitForNextEvent();
        }
        Thread.CurrentThread.Abort();
    }

With the EventArrived handler of...

    private void watcher_EventArrived(object obj, EventArrivedEventArgs e)
    {
            var newEvent = e.NewEvent;

            ManagementBaseObject targetInstance = (ManagementBaseObject)newEvent.GetPropertyValue("TargetInstance");

            string drivename = targetInstance.GetPropertyValue("Name").ToString();

Drivename ends up actually being the drive letter, such as D: or whatever...

Downside of that is the app needs to run with the correct privileges for the local WMI scope and it's slightly more intensive than passively handling window messages.

like image 130
dotalchemy Avatar answered Oct 10 '22 19:10

dotalchemy