Solved

Detecting USB Mass Storage Insertion from C#

Posted on 2007-11-28
10
4,764 Views
Last Modified: 2013-11-07
I need to detect the insertion and removal of USB Mass Storage Devices from C#. I have found some code (http://www.codeproject.com/dotnet/devicevolumemonitor.asp) which solves most of my problem however it also triggers when a user maps a network drive. Can someone suggest modifications or an alternative method.
/// <summary>

        /// WndProc method that traps all messages sent to the Handle

        /// </summary>

        /// <param name="aMessage">A Windows message</param>

        protected override void WndProc(ref Message aMessage)

        {

            BroadcastHeader lBroadcastHeader;

            Volume          lVolume;

            DeviceEvent     lEvent;
 

            base.WndProc(ref aMessage);

            if(aMessage.Msg==WM_DEVICECHANGE && fMonitor.Enabled)

            {

                lEvent = (DeviceEvent)aMessage.WParam.ToInt32();

                if (lEvent==DeviceEvent.Arrival || lEvent==DeviceEvent.RemoveComplete)

                {

                    lBroadcastHeader = (BroadcastHeader)Marshal.PtrToStructure(aMessage.LParam,typeof(BroadcastHeader));

                    if(lBroadcastHeader.Type==DeviceType.Volume)

                    {

                        lVolume = (Volume)Marshal.PtrToStructure(aMessage.LParam,typeof(Volume));

                        if((lVolume.Flags & (int)VolumeFlags.Media) == 0)

                        { 

                            fMonitor.TriggerEvents(lEvent==DeviceEvent.Arrival,lVolume.Mask);

                        }

                    }

                }

            }

        }

Open in new window

0
Comment
Question by:S31B1
  • 6
  • 3
10 Comments
 
LVL 7

Expert Comment

by:prosh0t
ID: 20367268
it looks like somebody else had the same problem, maybe this can help:

http://www.thescripts.com/forum/thread264280.html

also look at:
http://www.codeproject.com/dotnet/devicevolumemonitor.asp?df=100&forumid=15152&exp=0&fr=26

see the flags DBTF_MEDIA and DBTF_NET
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
ID: 20367723
Both the Volume and BroadcastHeader structures have a DeviceType.

Bob
0
 
LVL 4

Author Comment

by:S31B1
ID: 20368251
@The Learned One
On my system The Device Type returned for Network shares and Mass Storage devices are both Volume (0x00000002).

@prosh0t
So I'm looking at the VolumeFlags now, it seems that, in my limited testing:-

NET Share: Volume.Flags = 2
USB: Volume.Flags = 0
CDROM: Volume.Flags = 2002452481

Could you expalin any more about the Flags?

If I just test for Volume.Flags == 0 will this detect only the USB in all cases?
0
 
LVL 4

Author Comment

by:S31B1
ID: 20368263
as I understand it the Code above is calling into non-managed code, is there something in the framework I should be using in preference?

What is the "ManagementEventWatcher" all about?
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 20368623
If you want to go the WMI route, here is a class that will function as a USB device watcher.

Bob
// Add a reference to System.Management.dll to the project.
 

using System;

using System.Management;
 

public class Win32_UsbDriveWatcher

{

  private ManagementEventWatcher m_watcher;
 

  public delegate void DeviceInsertedEventHandler(object sender, Win32_UsbDriveInsertEventArgs e);
 

  public event DeviceInsertedEventHandler DeviceInserted;

  public event EventHandler DeviceRemoved;
 

  public void Start(int pollingInterval)

  {

    string queryString =

      "SELECT * " +

      " FROM __InstanceOperationEvent" +

      " WITHIN " + pollingInterval +

      " WHERE TargetInstance ISA 'Win32_DiskDrive'";
 

    EventQuery processQuery = new EventQuery(queryString);
 

    m_watcher = new ManagementEventWatcher(processQuery);

    m_watcher.EventArrived += new System.Management.EventArrivedEventHandler(EventArrived);

    m_watcher.Start();

  }
 

  private void EventArrived(object sender, System.Management.EventArrivedEventArgs e)

  {

    PropertyData instance = ((PropertyData)(e.NewEvent.Properties["TargetInstance"]));

    ManagementBaseObject obj = (ManagementBaseObject)instance.Value;

    Win32_UsbDriveInsertEventArgs args = new Win32_UsbDriveInsertEventArgs();

    if ((string)obj["InterfaceType"] == "USB")

    {

      args.IsCreated = (obj.ClassPath.ClassName == "__InstanceCreationEvent");

      args.DriveName = this.GetDriveLetterFromDisk((string)obj["Name"]);

      if (args.IsCreated)

      {

        if (DeviceInserted != null)

        {

          DeviceInserted(this, args);

        }

      }

      else

      {

        if (DeviceRemoved != null)

        {

          DeviceRemoved(this, EventArgs.Empty);

        }

      }

    }

  }
 

  private string GetDriveLetterFromDisk(string name)

  {

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

    string query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + name + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";

    ObjectQuery queryDrive = new ObjectQuery(query);

    ManagementObjectSearcher searcherDrive = new ManagementObjectSearcher(queryDrive);

    foreach (ManagementObject drive in searcherDrive.Get())

    {

      query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" +

        drive["DeviceID"] +

        "'} WHERE AssocClass = Win32_LogicalDiskToPartition";

      ObjectQuery queryPartition = new ObjectQuery(query);

      ManagementObjectSearcher searcherPartition = new ManagementObjectSearcher(queryPartition);

      foreach (ManagementObject disk in searcherPartition.Get())

      {

        return (string)disk["Name"];

      }

    }

    return string.Empty;

  }
 

}
 

public class Win32_UsbDriveInsertEventArgs : EventArgs

{

  public bool IsCreated;

  public string DriveName;

}

Open in new window

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 96

Assisted Solution

by:Bob Learned
Bob Learned earned 500 total points
ID: 20368649
Example:

Win32_UsbDriveWatcher watcher = new Win32_UsbDriveWatcher();
watcher.DeviceInserted += OnUsbDeviceInserted;
watcher.DeviceRemoved += OnUsbDeviceRemoved;
watcher.Start(5);

...

private void OnUsbDeviceInserted(object sender, Win32_UsbDriveInsertEventArgs e)
{
}

private void OnUsbDeviceRemoved(object sender, EventArgs e)
{
}

Bob
0
 
LVL 4

Author Comment

by:S31B1
ID: 20372285
Thanks, for the code I'm having a look at it now. A couple of issues. When I close the test program I have written I get an InvalidComObjectException. "Com object has been seperated from its underlying RCW cannot be used"

And it never seems to trigger!

It gets into the GetDriveLetterFromDisk function, attempts to itterate over the searcherDrive.Get() fails and drops right out, I don't get any errors either.

not sure if the two problems are related?
0
 
LVL 4

Author Comment

by:S31B1
ID: 20372289
Another thing, all things equal, If I get this new code working which is the preferred way of trapping this event in my c# winform?
0
 
LVL 4

Author Comment

by:S31B1
ID: 20372367
So, I've commented out the call to this.GetDriveLetterFromDisk and I now get my event raised. however it is always a Device Removed Event regardless of action.
0
 
LVL 4

Author Comment

by:S31B1
ID: 20372404
Sorry!

Next Question.

I notice there is a poling interval (as a parameter of the constructor) and in the query is this a value in seconds? Does this mean I could be waiting up to 5 seconds before i get a notification?

If so what is the smallest window of time I can sample and what would be the effect on system performance?
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

705 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now