|
-
Aug 7th, 2008, 03:27 PM
#1
Thread Starter
Frenzied Member
[2005] FilesystemWatcher and USB devices?
Hi!
In the app I am building, the user want to configure this just by inserting an usb sticl with the config file, the app should recognize this, scan the device for a config file use it and then disconnect the usb device and restart itself.
I read alittle about the filesystemwatcher, but nothing suggests it can detect changes like this, it can only monitor and react to an already mounted filesystem, right?
Anyone tried to do something similar?
kind regards
Henrik
-
Aug 7th, 2008, 03:32 PM
#2
Re: [2005] FilesystemWatcher and USB devices?
No, but you can scan the list of logical drives attached to the computer. Do it every so many seconds, and when a new drive suddenly appears, check it to see if it has a config file.
The only other option would be to hook into a system event that happens when a new disk drive gets mounted, but you're probably talking Windows API there.
-
Aug 7th, 2008, 03:38 PM
#3
Re: [2005] FilesystemWatcher and USB devices?
Use WMI to query the Win32_VolumeChangeEvent class and then use a ManagementEventWatcher object to watch for events raised by Win32_VolumeChangeEvent class.
You can read information on Win32_VolumeChangeEvent class here:
http://msdn.microsoft.com/en-us/library/aa394516.aspx
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
Aug 7th, 2008, 03:41 PM
#4
Thread Starter
Frenzied Member
Re: [2005] FilesystemWatcher and USB devices?
Hi!
I see, thats sad. Yes perhaps I could try using Windows API. What I need to do is actually very simple.
1) Detect that a removable device is plugged in, based on if it is empty or has an xml file I should do two different things
Empty = copy a big xml file with measurements to it
Xml = read the new config, copy it to another directory, restart.
All very simple but I need to know two things
1) When the device is plugged in
2) What unit name it got X:\ Y:\ etc so I can scan it...
Isn't there something in the My namespace that can be helpful? Just thinking...
/Henrik
-
Aug 7th, 2008, 05:48 PM
#5
Re: [2005] FilesystemWatcher and USB devices?
Yeah, My.Computer.FileSystem.Drives - this is probably what Jenner was referring to. You could check the collection of drives every 15 seconds or something and then when a new drive appears in this collection, you scan it to see if it contains this file.
Of course you could also try Stanav's method to see if that works better.
EDIT: I might be able to put together a way of doing it using Windows API but I think Stanavs solution is probably going to be easier to use than that
Last edited by chris128; Aug 7th, 2008 at 05:51 PM.
-
Aug 7th, 2008, 06:22 PM
#6
Re: [2005] FilesystemWatcher and USB devices?
OK well I've managed to get my test program to detect when a USB drive is connected to the system and produce a messagebox but I cant find any way of determining which drive letter was assigned to it I'm afraid.
Here's what I've got, its pretty simple, just overriding the WndProc event of my form:
vb Code:
'Declare the constants that we will use in our event
Private Const WM_DEVICECHANGE As Integer = &H219
Private Const DBT_DEVICEARRIVAL As Integer = 32768
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_DEVICECHANGE Then
If m.WParam = DBT_DEVICEARRIVAL Then
'\\\ Replace the messagebox with your scanning code if you get it to work \\\
MessageBox.Show("Removable Drive Detected")
End If
End If
MyBase.WndProc(m)
End Sub
You could just copy and paste that into your form and then try plugging in a USB drive to see it in action
Hope it helps a bit
Chris
EDIT: I've asked in the API forum to see if anyone can help - http://www.vbforums.com/showthread.p...53#post3305053
Last edited by chris128; Aug 7th, 2008 at 06:49 PM.
-
Aug 8th, 2008, 03:46 AM
#7
Re: [2005] FilesystemWatcher and USB devices?
I just looked at the method that stanav mentioned and it seems like this would be much easier to use as the drive letter is more easily accessible. So you should give that a go instead of using the API method that I am [i]trying[i/] to get going.
I'm still going to try get the API working though just for the sake of it
-
Aug 8th, 2008, 04:20 AM
#8
Thread Starter
Frenzied Member
Re: [2005] FilesystemWatcher and USB devices?
Hi!
I made a successful implementation using the drives info, here is an implementation (in C# though)
(Very untested, a simple lab experiement)
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.IO;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public class RemovableDeviceMonitor
{
public delegate void RemovableDeviceDetectedEventHandler(object sender, RemovableDeviceDetectedEventArgs e);
private BackgroundWorker myWorker;
public event RemovableDeviceDetectedEventHandler RemovableDeviceDetected;
public void StartMonitor()
{
// Start background worker to do some monitoring
myWorker = new BackgroundWorker();
myWorker.WorkerReportsProgress = false;
myWorker.WorkerSupportsCancellation = true;
myWorker.DoWork += new DoWorkEventHandler(StartMonitorDevices);
myWorker.RunWorkerAsync();
}
private void StartMonitorDevices(object sender, DoWorkEventArgs e)
{
// Do this every second
while (!myWorker.CancellationPending)
{
// Check the device enum
DriveInfo[] Drivers = DriveInfo.GetDrives();
foreach (DriveInfo drive in Drivers)
{
if (drive.DriveType == DriveType.Removable && drive.IsReady)
{
System.Diagnostics.Debug.Write("Removable Device found!! \n");
if (RemovableDeviceDetected != null)
{
// someone is listening, signal StateChanged
System.Diagnostics.Debug.Write("Someone wants to know, firing event! \n");
RemovableDeviceDetectedEventArgs args = new RemovableDeviceDetectedEventArgs(drive.Name.ToString());
RemovableDeviceDetected(this, args);
//return;
}
}
System.Diagnostics.Debug.Write("No removable devices found \n");
}
System.Threading.Thread.Sleep(1000);
}
return;
}
public void StopMonitor()
{
this.myWorker.CancelAsync();
Debug.Write("Thread cancelled!\n");
}
}
public class RemovableDeviceDetectedEventArgs : EventArgs
{
public readonly String DeviceName;
public RemovableDeviceDetectedEventArgs(String DeviceName)
{
this.DeviceName = DeviceName;
}
}
}
kind regards
Henrik
[/code]
-
Aug 8th, 2008, 04:42 AM
#9
Re: [2005] FilesystemWatcher and USB devices?
I finally got the API method working, I prefer this method (or Stanavs) method over the method that Henrik posted as it is a little more robust/reliable and does not require constant checking of available drves (which could have a slight performance hit).
Here's my entire form code, you should be able to just copy and paste it into a blank form and then test it out:
vb Code:
Imports System.Runtime.InteropServices
Public Class Form1
Private Const WM_DEVICECHANGE As Integer = &H219
Private Const DBT_DEVICEARRIVAL As Integer = &H8000
Private Const DBT_DEVTYP_VOLUME As Integer = &H2
'Device information structure
Public Structure DEV_BROADCAST_HDR
Public dbch_size As Int32
Public dbch_devicetype As Int32
Public dbch_reserved As Int32
End Structure
'Volume information Structure
Private Structure DEV_BROADCAST_VOLUME
Public dbcv_size As Int32
Public dbcv_devicetype As Int32
Public dbcv_reserved As Int32
Public dbcv_unitmask As Int32
Public dbcv_flags As Int16
End Structure
'<<<< Function that gets the drive letter from the unit mask >>>>
Private Function GetDriveLetterFromMask(ByRef Unit As Int32)
Dim i As Integer
For i = 0 To 25
If Unit And i Then Exit For
Unit = Unit >> 1
Next
Return Chr(i + 1 + Asc("A"))
End Function
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_DEVICECHANGE Then
If m.WParam = DBT_DEVICEARRIVAL Then
Dim DeviceInfo As DEV_BROADCAST_HDR
DeviceInfo = Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_HDR))
If DeviceInfo.dbch_devicetype = DBT_DEVTYP_VOLUME Then
Dim Volume As DEV_BROADCAST_VOLUME
Volume = Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_VOLUME))
Dim DriveLetter As String = (GetDriveLetterFromMask(Volume.dbcv_unitmask) & ":\")
Dim FileList() As String = IO.Directory.GetFiles(DriveLetter, "test.txt")
If FileList.Count > 0 Then
MessageBox.Show("Found Config File")
'<<<< The config file has been found >>>>
'<<<< So do your processing of it here >>>>
Else
MessageBox.Show("Could not find config file")
'<<<< Config file has not been found >>>>
End If
End If
End If
End If
MyBase.WndProc(m)
End Sub
End Class
Obviously in my example I am just searching the newly connected drive for a file called Test.txt but you can change this to whatever
Last edited by chris128; Aug 8th, 2008 at 04:46 AM.
-
Aug 8th, 2008, 08:08 AM
#10
Re: [2005] FilesystemWatcher and USB devices?
Here's some really nice code I found and converted. It'll detect USB drives specifically, whether they're being added or removed, and the volume name and drive letter. Just make a new project, and copy-paste it over the default form's code. Be sure to add System.Management to your References as well.
Code:
Imports System.Management
Public Class frmForm
Private WithEvents mew As ManagementEventWatcher
Private Sub frmForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
mew.Stop()
End Sub
Private Sub frmForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
StartDetection()
End Sub
Private Sub StartDetection()
Dim queryWql As New WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_DiskDrive'")
mew = New ManagementEventWatcher(queryWql)
mew.Start()
End Sub
Private Sub Arrived(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs) Handles mew.EventArrived
Dim mboE, mboTarget As ManagementBaseObject
mboE = DirectCast(e.NewEvent, ManagementBaseObject)
mboTarget = DirectCast(mboE("TargetInstance"), ManagementBaseObject)
Select Case mboE.ClassPath.ClassName
Case "__InstanceCreationEvent"
If mboTarget("InterfaceType").Equals("USB") Then
MessageBox.Show(String.Format("{0} (Drive letter {1}) has been plugged in", mboTarget("Caption"), GetDriveLetterFromDisk(mboTarget("Name").ToString)))
Else
MessageBox.Show(mboTarget("InterfaceType").ToString)
End If
Case "__InstanceDeletionEvent"
If mboTarget("InterfaceType").Equals("USB") Then
MessageBox.Show(String.Format("{0} has been unplugged", mboTarget("Caption")))
Else
MessageBox.Show(mboTarget("InterfaceType").ToString)
End If
Case Else
MessageBox.Show(String.Format("Nope: {0}", mboTarget("Caption")))
End Select
End Sub
Private Function GetDriveLetterFromDisk(ByVal strName As String) As String
Dim oqPart As New ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & strName.Replace("\", "\\") & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition")
Dim mosPart As New ManagementObjectSearcher(oqPart)
Dim strResponse As New List(Of String)
For Each mobPart As ManagementObject In mosPart.Get()
Dim oqDisk As New ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & mobPart("DeviceID").ToString & """} WHERE AssocClass = Win32_LogicalDiskToPartition")
Dim mosDisk As New ManagementObjectSearcher(oqDisk)
For Each mobDisk As ManagementObject In mosDisk.Get()
strResponse.Add(mobDisk("Name").ToString)
Next
Next
Return String.Join(",", strResponse.ToArray)
End Function
End Class
-
Aug 8th, 2008, 09:04 AM
#11
Re: [2005] FilesystemWatcher and USB devices?
Dammit I knew it was a waste of time getting that API code working lol ah well, I learnt a bit from it
-
Aug 8th, 2008, 09:11 AM
#12
Re: [2005] FilesystemWatcher and USB devices?
Heck, after having to deal with those cryptic queries, I'm ready to use that API code of yours
-
Aug 8th, 2008, 09:22 AM
#13
Re: [2005] FilesystemWatcher and USB devices?
haha yeah that code you posted is pretty impossible to read through and understand what its doing. At least the OP has a few different options now
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|