5

I build a little script that checks if a USB Stick with a given Name ist plugged into the Computer, but now I want to build a service around this Script to watch if the Stick plugged in or not. At first I try to do this with the filewatcher and create a file on the Stick but if remove the stick from the pc and replugged the filewatcher dosent realize it. The following script check one time if the Stick is plugged in or not, but I need a script to loop this DriveInfo.GetDrive function. I dont know if the best way is to buil a 10 second timer loop around this function or if there is any watcher class for removeable devices in the .NET Framework. Here comes the Script:

public static void Main()
{
    Run();
}

public static void Run()
{                     
    var drives = DriveInfo.GetDrives()
        .Where(drive => drive.IsReady && drive.DriveType == DriveType.Removable);
    if (drives.Count() > 0)
    {
        foreach (var drive in drives)
        {
           if (drive.VolumeLabel == "TESTLABEL") Console.WriteLine("USB Stick is plugged in");
        }
    }
}
mbx
  • 6,292
  • 6
  • 58
  • 91
kockiren
  • 711
  • 1
  • 12
  • 33
  • 2
    check this post: http://stackoverflow.com/questions/6003822/how-to-detect-a-usb-drive-has-been-plugged-in?rq=1 – celerno Aug 01 '13 at 17:14
  • Thanks for your answer, but this is the content of my Script, but now I search for a solution to check in a loop. But dont know if there watcher Process like Filewatcher for the Drives. – kockiren Aug 01 '13 at 17:21
  • how often do you want the service to check if the drive still is plugged in? – S Grimminck Aug 01 '13 at 17:22
  • This is the question, the filewatcher do this near realtime, so if it possible I want to watch if a drive plugged in near realtim, if this not possible from standard so it was enough to check every 30seconds. – kockiren Aug 01 '13 at 18:43
  • If you want it to run near-realtime, why not just surround your `Run()` method call in a `while(true){ }` loop? This creates an infinite loop (forget for the moment about how bad this is ...). As for creating a service - if you mean creating a Windows service, have a look at [Topshelf](http://topshelf-project.com/) – Sameer Singh Aug 05 '13 at 09:05
  • Is there a solution to hook into a Windows Event? I want to send my script to sleep until a event occurs. I think this is a better way to implement that function than a infinite loop. – kockiren Aug 05 '13 at 12:55
  • 2
    See also http://stackoverflow.com/questions/1976573/using-registerdevicenotification-in-a-net-app – Peter Ritchie Aug 06 '13 at 17:52

1 Answers1

9

You can hook to (USB) Events using the ManagementEventWatcher.

Working example for LinqPad paraphrasing this neat answer which uses the Win32_DeviceChangeEvent:

// using System.Management;
// reference System.Management.dll
void Main()
{    
    using(var control = new USBControl()){
        Console.ReadLine();//block - depends on usage in a Windows (NT) Service, WinForms/Console/Xaml-App, library
    }
}

class USBControl : IDisposable
    {
        // used for monitoring plugging and unplugging of USB devices.
        private ManagementEventWatcher watcherAttach;
        private ManagementEventWatcher watcherDetach;

        public USBControl()
        {
            // Add USB plugged event watching
            watcherAttach = new ManagementEventWatcher();
            watcherAttach.EventArrived += Attaching;
            watcherAttach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
            watcherAttach.Start();

            // Add USB unplugged event watching
            watcherDetach = new ManagementEventWatcher();
            watcherDetach.EventArrived += Detaching;
            watcherDetach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
            watcherDetach.Start();
        }

        public void Dispose()
        {
            watcherAttach.Stop();
            watcherDetach.Stop();
            //you may want to yield or Thread.Sleep
            watcherAttach.Dispose();
            watcherDetach.Dispose();
            //you may want to yield or Thread.Sleep
        }

        void Attaching(object sender, EventArrivedEventArgs e)
        {
            if(sender!=watcherAttach)return;
            e.Dump("Attaching");
        }

        void Detaching(object sender, EventArrivedEventArgs e)
        {
            if(sender!=watcherDetach)return;
            e.Dump("Detaching");
        }

        ~USBControl()
        {
            this.Dispose();// for ease of readability I left out the complete Dispose pattern
        }
    }

When attaching a USB-Stick I'll receive 7 attach (resp. detach) Events. Customize the Attaching/Detaching methods as you like. The blocking part is left to the reader, depending on his needs, with a Windows Service you wouldn't need to block at all.

Community
  • 1
  • 1
mbx
  • 6,292
  • 6
  • 58
  • 91
  • Any idea on how to make it so you don't receive 7 attach responses? – Blue Eyed Behemoth Dec 23 '15 at 21:41
  • @BlueEyedBehemoth Depends on what you're up to. Looking at my eventargs, I was able to establish a "works for this specific thumb drive"-filter kind of solution. I used the `Win32_VolumeChangeEvent` to [detect a new drive just as shown here with only one event](https://gist.github.com/embix/997b825a7f3ea11764d3). If your device is different, your solution will be too. – mbx Dec 25 '15 at 22:39
  • I just need it to trigger once when a USB device is plugged in. That's all. The USB device I use appears as a storage device. – Blue Eyed Behemoth Dec 28 '15 at 16:45
  • 1
    @BlueEyedBehemoth then filtering by `Win32_VolumeChangeEvent` is your best option. – mbx Dec 28 '15 at 18:15