Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Detect USB device Insertion/Removal (drive letter)

Posted on 2006-04-06
14
Medium Priority
?
1,435 Views
Last Modified: 2012-08-13
hi experts exchange;

I found the following code snippet on ee, and it successfully allows me to detect a USB device (storage device in particular):-

      public enum DeviceEvent : int
      {
            Arrival = 0x8000,                  //DBT_DEVICEARRIVAL
            QueryRemove = 0x8001,                   //DBT_DEVICEQUERYREMOVE
            QueryRemoveFailed = 0x8002,      //DBT_DEVICEQUERYREMOVEFAILED
            RemovePending = 0x8003,                   //DBT_DEVICEREMOVEPENDING
            RemoveComplete = 0x8004,             //DBT_DEVICEREMOVECOMPLETE
            Specific = 0x8005,                         //DBT_DEVICEREMOVECOMPLETE
            Custom = 0x8006                               //DBT_CUSTOMEVENT
      }

      protected override void WndProc(ref Message m)
      {
            base.WndProc(ref m);
            const int WM_DEVICECHANGE = 0x0219;
            DeviceEvent lEvent;

            if(m.Msg == WM_DEVICECHANGE)
            {
                  lEvent = (DeviceEvent) m.WParam.ToInt32();
                        
                  if (lEvent == DeviceEvent.Arrival)
                        MessageBox.Show("USB DEVICE DETECTED");
                  else if (lEvent == DeviceEvent.RemoveComplete)
                        MessageBox.Show("USB DEVICE REMOVED");
            }
      }


My question:-
As far as I understand it, the above code detects any device which is detected, is there a way I can only detect USB devices, I need to know the drive letter of the inserted usb device.

Thanks
0
Comment
Question by:Programmer_to_be
  • 8
  • 5
14 Comments
 
LVL 6

Expert Comment

by:enwhysee
ID: 16399494
This post describes how to do it ...

http://groups.google.com/group/microsoft.public.windowsxp.device_driver.dev/msg/d417a756065e7156?hl=en&lr=lang_en&ie=UTF-8&oe=UTF-8

See the Example code section on this site for actual example code on how to do it in C#:
http://lvr.com/hidpage.htm#MyExampleCode
0
 
LVL 41

Accepted Solution

by:
graye earned 400 total points
ID: 16402424
...and yet another example here (in VB.Net, but hey... the concepts are the same)

http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21599899.html
0
 

Author Comment

by:Programmer_to_be
ID: 16417123
Hi graye.

I tried your example by directly copying it in a VB.NET application, and it worked great, when I converted it to C#.NET, it fires the event when the USB device is removed, but I can't seem to get the event fired when the USB device is attached, do you notice anything that I'm doing wrong (below):

using System.Management;

private ManagementEventWatcher m_MediaConnectWatcher;

            private void button1_Click(object sender, System.EventArgs e)
            {
                  string query = "SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE TargetInstance ISA \"Win32_DiskDrive\"";
                  this.m_MediaConnectWatcher = new ManagementEventWatcher(query);
                  this.m_MediaConnectWatcher.EventArrived += new EventArrivedEventHandler(m_MediaConnectWatcher_EventArrived);
                  this.m_MediaConnectWatcher.Start();
            }

            private void m_MediaConnectWatcher_EventArrived(object sender, EventArrivedEventArgs e)
            {
                  ManagementBaseObject mbo, obj;

                  mbo = (ManagementBaseObject) e.NewEvent;
                  obj = (ManagementBaseObject) mbo["TargetInstance"];

                  switch (mbo.ClassPath.ClassName)
                  {
                        case "__InstanceCreationEvent":
                              
                              if (obj["InterfaceType"].ToString() == "USB")
                              {
                                    this.listBox1.Items.Add(obj["Caption"].ToString() + " (Drive letter " + this.GetDriveLetterFromDisk(obj["Name"].ToString()) + ") has been plugged in");
                              }
                              break;

                        case "__InstanceDeletionEvent":

                              if (obj["InterfaceType"].ToString() == "USB")
                              {
                                    this.listBox1.Items.Add(obj["Caption"].ToString() + " has been unplugged");
                              }
                              break;
                  }
            }

            private string GetDriveLetterFromDisk(string name)
            {
                  ObjectQuery oq_part, oq_disk;
                  ManagementObjectSearcher mos_part, mos_disk;
                  string ans = string.Empty;

                  name = name.Replace(@"\", "\\");

                  oq_part = new ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=\"" + name + "\"} WHERE AssocClass = Win32_DiskDriveToDiskPartition");
                  mos_part = new ManagementObjectSearcher(oq_part);

                  foreach (ManagementObject obj_part in mos_part.Get())
                  {
                        oq_disk = new ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=\"" + obj_part["DeviceID"] + "\"} WHERE AssocClass = Win32_LogicalDiskToPartition");
                        mos_disk = new ManagementObjectSearcher(oq_disk);

                        foreach (ManagementObject obj_disk in mos_disk.Get())
                        {
                              ans += obj_disk["Name"] + ",";
                        }
                  }

                  return ans.Trim('c');
            }

            private void button2_Click(object sender, System.EventArgs e)
            {
                  this.m_MediaConnectWatcher.Stop();
            }
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:Programmer_to_be
ID: 16417353
hi;

I figured it out, it was the the line

name = name.Replace(@"\", "\\");   -- should have been --  name = name.Replace("\\", "\\\\");

Thanks graye, one last thing, I changed the following query string:-

string query = "SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE TargetInstance ISA \"Win32_DiskDrive\"";

to

 "..WITHIN 2.."

and it seems to detect the usb device faster, was there any reason for you to initially have WITHIN 10? is it ok to lower that ? because it still seems to work ok but faster!

thanks again.
0
 
LVL 41

Expert Comment

by:graye
ID: 16417376
I see some minor "translation errors"...

               name = name.Replace(@"\", @"\\");
                                                          ^
               return ans.Trim(',');
                                       ^
After those two minor changes, it works for me...
0
 
LVL 41

Expert Comment

by:graye
ID: 16417409
No particular reason... I was just trying to reduce the "poll time", so that the program wouldn't use as many resources.
0
 

Author Comment

by:Programmer_to_be
ID: 16417839
Thanks graye, it works a treat :-)
0
 

Author Comment

by:Programmer_to_be
ID: 16440378
Hi graye; I'm sorry to post in a closed question but I couldnt think of any other way to get your attention on a problem that I'm having with the code you provided. I'll open another question to give you further points relating to this question.

When the EventArrived event fires and indicates that a USB device has been attached, I am trying to open another form, the form opens but does not respond at all, it simply changes to the colour white and when I hover the mouse over the opened form, the loading curser appears. To try and convey what I'm trying to do, see below:-

          private void m_MediaConnectWatcher_EventArrived(object sender, EventArrivedEventArgs e)
          {
               ManagementBaseObject mbo, obj;

               mbo = (ManagementBaseObject) e.NewEvent;
               obj = (ManagementBaseObject) mbo["TargetInstance"];

               switch (mbo.ClassPath.ClassName)
               {
                    case "__InstanceCreationEvent":
                         
                         if (obj["InterfaceType"].ToString() == "USB")
                         {
                             Form f2 = new Form();
                             f2.Show(); //Form 2 opens, but does not respond
                         }
                         break;

                    case "__InstanceDeletionEvent":

                         System.Windows.Forms.MessageBox.Show("Device removed");
                         break;
               }
          }



If your able to recreate this problem, would you know why this is happening?
Many thanks.
0
 
LVL 41

Expert Comment

by:graye
ID: 16441355
Let's start with the basics.... normally you'd create an new instance of a form class by it's full name (but I'm assuming that that's just a typo)

       Form2 f2 = new Form2();

Secondly, this is really a multi-threaded application (even though you didn't really do anything that specifically asked for it to be).  That's just the way that WMI was designed to operate.  So, what's happening, is that the form is shown properly, but control is passed back to the calling routine and the new form never gets focus.  Rather than bore you with all of the reasons why, let's just try this simple fix instead.  

       f2.ShowDialog();
0
 

Author Comment

by:Programmer_to_be
ID: 16441531
graye I can't thank you enough for the help you've provided.

Its working great now. What I originally was trying to do was that when a USB device was detected I was raising an event, the main form of my application subscribed to the event and when the event got fired the event handling method would add a new TabPage to a TabControl. The TabPage was added OK, but its background was white and I was unable to remove it at runtime too (I don't know whether this was because of the multi-threading issue you told me about or not because it does have similarities in behaviour to the form problem), if it was, is there any non-simple way to have my first solution (using a TabPage) work? I eventually ended up just showing a new form (which works now) because I couldnt get the TabPage solution to work.

I'll create a new post in the C# TA, if you could post any message there I'll assign the points to you for the additional help you have provided. Thanks.
0
 

Author Comment

by:Programmer_to_be
ID: 16441901
Hi graye; a thing which seems to be causing a problem using the ShowDialog method to open the form is that I am unable to close the form when the removal event arrives, my code below may explain this better:

          private Form2 f2;
         
           private void m_MediaConnectWatcher_EventArrived(object sender, EventArrivedEventArgs e)
           {
               ManagementBaseObject mbo, obj;

               mbo = (ManagementBaseObject) e.NewEvent;
               obj = (ManagementBaseObject) mbo["TargetInstance"];

               switch (mbo.ClassPath.ClassName)
               {
                    case "__InstanceCreationEvent":
                         
                         if (obj["InterfaceType"].ToString() == "USB")
                         {
                             f2 = new Form2();
                             f2.ShowDialog();                          
                         }
                         break;

                    case "__InstanceDeletionEvent":

                         if (obj["InterfaceType"].ToString() == "USB")
                         {
                              System.Windows.Forms.MessageBox.Show("Device removed");
                              f2.Close();
                         }
                         break;
               }
          }
 
When Form2 is opened using ShowDialog and I take the USB device out, the deletion event never fires until i manually close Form2, once Form2 is closed the event then fires (giving the message box) and f2.Close(); is then executed... (too late as the form is closed already).

Any ideas?
0
 
LVL 41

Expert Comment

by:graye
ID: 16444764
I know that nobody likes reading the manual (that's why web sites like this are so popular), but....

Let's start off with some background information on the subject of threading:
http://msdn2.microsoft.com/en-us/library/ms173178.aspx

Then a "how to" article on threading:
http://support.microsoft.com/default.aspx?scid=kb;en-us;815804
0
 

Author Comment

by:Programmer_to_be
ID: 16447681
Hi graye; I understand threading to a good level, my understanding of this problem is that the form gets shown on a different thread (created by WMI), and when that event method finishes execution, the thread which the form was created on gets killed too... what I'm having difficulty in implementing is that I don't know how to execute that form creation code (creating a form object and calling .Show) on the current application thread. Can you point me in the right direction on where I need to look?

Thanks.
0
 

Author Comment

by:Programmer_to_be
ID: 16449721
Hi again graye, did a bit of reading (should do this more often) and came across the Control.Invoke method, used that and its working fine.

Thanks for the additional help!
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

571 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question