Looking into possibility of making an USB distributed application
that will autostart on insertion of an USB stick and shutdown when removing the stick
Will use .Net and C#.
Looking for suggestion how to approach this using C#?
Update: Two possible solutions implementing this as a service.
- override WndProc
or
- using WMI query with ManagementEventWatcher
You can use WMI, it is easy and it works a lot better than WndProc solution with services.
Here is a simple example:
using System.Management;
ManagementEventWatcher watcher = new ManagementEventWatcher();
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Query = query;
watcher.Start();
watcher.WaitForNextEvent();
This works well for me, plus you can find out more information about the device.
using System.Management;
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
Adding to VitalyB's post.
To raise an event where ANY USB device is inserted, use the following:
var watcher = new ManagementEventWatcher();
var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Query = query;
watcher.Start();
This will raise an event whenever a USB device is plugged. It even works with a National Instruments DAQ that I'm trying to auto-detect.
VitalyB's answer does't cover remove of the device. I changed it a bit to trigger the event both when media is inserted and removed and also code to get the drive letter of the inserted media.
using System;
using System.Management;
namespace MonitorDrives
{
class Program
{
public enum EventType
{
Inserted = 2,
Removed = 3
}
static void Main(string[] args)
{
ManagementEventWatcher watcher = new ManagementEventWatcher();
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2 or EventType = 3");
watcher.EventArrived += (s, e) =>
{
string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
EventType eventType = (EventType)(Convert.ToInt16(e.NewEvent.Properties["EventType"].Value));
string eventName = Enum.GetName(typeof(EventType), eventType);
Console.WriteLine("{0}: {1} {2}", DateTime.Now, driveName, eventName);
};
watcher.Query = query;
watcher.Start();
Console.ReadKey();
}
}
}
A little bit edit on all above answer:
using System.Management;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
bgwDriveDetector.DoWork += bgwDriveDetector_DoWork;
bgwDriveDetector.RunWorkerAsync();
}
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
MessageBox.Show(driveName + " inserted");
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
MessageBox.Show(driveName + " removed");
}
void bgwDriveDetector_DoWork(object sender, DoWorkEventArgs e)
{
var insertQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += DeviceInsertedEvent;
insertWatcher.Start();
var removeQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
var removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += DeviceRemovedEvent;
removeWatcher.Start();
}
}
You can also use WMI to detect insertion events. It's a little bit more complicated than monitoring for WM_CHANGEDEVICE messages, but it does not require a window handle which may be useful if you are running in the background as a service.
Try WM_CHANGEDEVICE handling.
My complete answer can be found here as a gist
I found the answer to determining the drive letter from the serial # from this question/answer
How to get the drive letter of USB device using WMI
And I modified Phil Minor's code to make it reactive:
public class UsbDetector : IUsbDetector
{
private const string Query = "SELECT * FROM {0} WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'";
private const string CreationEvent = "__InstanceCreationEvent";
private const string DeletionEvent = "__InstanceDeletionEvent";
private const int ReplayNumber = 1;
private readonly Subject<USBDeviceInfo> adds = new Subject<USBDeviceInfo>();
private readonly Subject<USBDeviceInfo> removes = new Subject<USBDeviceInfo>();
public UsbDetector()
{
var bgwDriveDetector = new BackgroundWorker();
bgwDriveDetector.DoWork += DoWork;
bgwDriveDetector.RunWorkerAsync();
}
public IObservable<USBDeviceInfo> Adds => adds.AsObservable();
public IObservable<USBDeviceInfo> Removes => removes.AsObservable();
private void DoWork(object sender, DoWorkEventArgs e)
{
SubscribeToEvent(CreationEvent, adds);
SubscribeToEvent(DeletionEvent, removes);
}
private static void SubscribeToEvent(string eventType, IObserver<USBDeviceInfo> observer)
{
WqlEventQuery wqlEventQuery = new WqlEventQuery(string.Format(Query, eventType));
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(wqlEventQuery);
var observable = Observable.FromEventPattern<EventArrivedEventHandler, EventArrivedEventArgs>(
h => insertWatcher.EventArrived += h,
h => insertWatcher.EventArrived -= h).Replay(ReplayNumber);
observable.Connect();
observable.Select(a => a.EventArgs).Select(MapEventArgs).Subscribe(observer);
insertWatcher.Start();
}
private static USBDeviceInfo MapEventArgs(EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
string deviceId = (string)instance.GetPropertyValue("DeviceID");
string serialNr = deviceId.Substring(deviceId.LastIndexOf('\\')).Replace("\\", "");
char driveLetter = GetDriveLetter(serialNr).First();
return new USBDeviceInfo(deviceId, serialNr, driveLetter);
}
Here is what we did with C# .Net 4.0 under a WPF app. We are still searching for an answer to "how to tell WHICH device type was inserted/removed", but this is a start:
using System.Windows.Interop;
...
public partial class MainWindow : Window
{
...
public MainWindow()
{
...
}
//============================================================
// WINDOWS MESSAGE HANDLERS
//
private const int WM_DEVICECHANGE = 0x0219; // int = 537
private const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x00000004;
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_DEVICECHANGE)
{
ReadDongleHeader();
}
return IntPtr.Zero;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.ComponentModel;
namespace ConsoleApplication4
{
public class usbState
{
public usbState()
{
}
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
public void bgwDriveDetector_DoWork(object sender, DoWorkEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
}
}
class Class1
{
private static void Main(string[] args)
{
usbState usb= new usbState();
BackgroundWorker bgwDriveDetector = new BackgroundWorker();
bgwDriveDetector.DoWork += usb.bgwDriveDetector_DoWork;
bgwDriveDetector.RunWorkerAsync();
bgwDriveDetector.WorkerReportsProgress = true;
bgwDriveDetector.WorkerSupportsCancellation = true;
// System.Threading.Thread.Sleep(100000);
Console.ReadKey();
}
}
}
Related
I have two functions. One is for query in WMI for USB devices, and 2nd one is for detect device remove/insertion. Both of them work independently very well. The problem starts when I trying to make the function responsible for detecting devices trigger function responsible for listing devices. Refresh the list when I connect or remove devices. It shows that the application is in "break mode" because of the threads.
I know that I will have to take for example the device detection function and put it to different thread and send for example integer 0/1 when devices are inserted/removed so that will trigger the list function in the GUI thread. The problem is that I have no idea how to do it ;/.
Device list code:
private void button1_Click(object sender, EventArgs e)
{
listView1.Items.Clear();
ManagementObjectSearcher s =
new ManagementObjectSearcher("root\\CIMV2", #"SELECT * FROM Win32_PnPEntity where DeviceID Like ""USB%""");
try
{
foreach (ManagementObject device in s.Get())
{
string Name = device.GetPropertyValue("Name").ToString();
ListViewItem items = new ListViewItem(Name);
string Description = device.GetPropertyValue("Description").ToString();
items.SubItems.Add(Description);
string Caption = device.GetPropertyValue("Caption").ToString();
items.SubItems.Add(Caption);
string PNPDeviceID = device.GetPropertyValue("PNPDeviceID").ToString();
items.SubItems.Add(PNPDeviceID);
string DeviceID = device.GetPropertyValue("DeviceID").ToString();
items.SubItems.Add(DeviceID);
string Service = device.GetPropertyValue("Service").ToString();
items.SubItems.Add(Service);
string Status = device.GetPropertyValue("Status").ToString();
items.SubItems.Add(Status);
string Manufacturer = device.GetPropertyValue("Manufacturer").ToString();
items.SubItems.Add(Manufacturer);
Boolean zmienna6 = (Boolean)device.GetPropertyValue("ConfigManagerUserConfig");
string ConfigManagerUserConfig = zmienna6.ToString();
items.SubItems.Add(ConfigManagerUserConfig);
/// string zmienna7 = (String)device.GetPropertyValue("ProtocolCode");
listView1.Items.Add(items);
}
}
catch (ManagementException ex)
{
MessageBox.Show("An error occurred while querying for WMI data: " + ex.Message);
}
Function for detecting devices:
private void Form1_Load(object sender, EventArgs e)
{
bgwDriveDetector.DoWork += bgwDriveDetector_DoWork;
bgwDriveDetector.RunWorkerAsync();
}
/// detection of the device con or discon
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
/// send intiger or string 1
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
/// send intiger or string 0
}
void bgwDriveDetector_DoWork(object sender, DoWorkEventArgs e)
{
var insertQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += DeviceInsertedEvent;
insertWatcher.Start();
var removeQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
var removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += DeviceRemovedEvent;
removeWatcher.Start();
}
I am trying to implement the code from the following link: Detecting USB drive insertion and removal using windows service and c#
I think the issue I am having is that my main UI thread isn't being notified by the background thread when the device is inserted or removed. I verified this by not being able to update the content of a label in my user control.
I have included my source code below:
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
MessageBox.Show(property.Name + " = " + property.Value); // Dialog box appears as expected.
StatusMessage.Content = $"{property.Name} = {property.Value}";
}
StatusMessage.Content = "Removable Drive detected!"; //label content should be updated here, and for some reason it is not.
bool isDriveRemoved = FindRemovableDrive(); //get the drive info
if (isDriveRemoved || Count > 0)
{
Count = 0;
}
else
{
Count++;
}
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
MessageBox.Show(property.Name + " = " + property.Value); // Dialog box appears as expected, but label is not updated.
}
StatusMessage.Content = $"{property.Name} = {property.Value}";
FileMenu.Items.Clear(); // the file menu should be getting cleared here.
}
private void backgroundWorker1_DoWork(object sender, RoutedEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += DeviceInsertedEvent;
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += DeviceRemovedEvent;
removeWatcher.Start();
// Do something while waiting for events
//Thread.Sleep(10000);
}
-Any input/solutions would be greatly appreciated.
Thanks for your time,
Michael
Rather than regularly scanning devices you can use a WMI Events to be notified when there is a hardware change.
Starting a listener for plug & play events:
var wmiPath = new ManagementPath(#"root\cimv2");
var scope = new ManagementScope(wmiPath);
scope.Connect();
var instanceQuery = new WqlEventQuery("__InstanceOperationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_PnPEntity\"");
wmiWatcher = new ManagementEventWatcher(scope, instanceQuery);
wmiWatcher.EventArrived += OnInstanceEvent;
wmiWatcher.Start();
The event handler:
private void OnInstanceEvent(object sender, EventArrivedEventArgs ea) {
var eventType = (string)ea.NewEvent["__CLASS"];
var targetWmiObj = ea.NewEvent["TargetInstance"] as ManagementBaseObject;
var deviceId = (string)targetWmiObj["deviceId"];
if (String.Equals("__InstanceCreationEvent", (string)ea.NewEvent["__CLASS"], StringComparison.Ordinal)) {
if (/* Filter on the device id for what is interesting here*/) {
// Handle relevant device arriving
}
}
}
There are other values of NewEvent["__CLASS"] for other event types (including device removal).
PS. This is (partial) code from a WinForms app that monitored for a specialised device being plagged in and then downloaded/uploaded data from it. All the work was done in the thread pool: everything here should just work under WPF.
I am working on a C# application. My requirement is that I have to detect (trigger an event) whenever a USB device gets connected to the PC and pass that connected port to another event if the attached device Vendor Id/Manufacturer is "FTDI".
My code for this is:
public class usbState
{
public static List<string> exisitngComPorts = new List<string>();
public event EventHandler<MyEventArgs> DeviceAttached;
public event EventHandler<MyEventArgs> DeviceRemoved;
public usbState()
{
}
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
string[] newlyAddedComPorts = SerialPort.GetPortNames();
string[] result = newlyAddedComPorts.Except(exisitngComPorts).ToArray();
exisitngComPorts.Add(result[0]);
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
string[] newlyRemovedComPorts = SerialPort.GetPortNames();
string[] result = exisitngComPorts.Except(newlyRemovedComPorts).ToArray();
exisitngComPorts.Remove(result[0]);
}
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
}
The code above does detect whenever a new device gets connected, but I am unable to get the Vendor Id/Manufacturer information, this information can be obtained from "ManagementObject" but the Device Id or PnpDeviceId returned by "ManagementBaseObject" and "ManagementObject" are different. How can I obtain the Vendor Id/Manufacturer information. The information which I am looking for is available in Device Manager, see below image.
How can I obtain this information from my existing code.
I have managed to do it my using ManagementObjectCollection. I did two comparisons, first, attached port with the port given my ManagementObject and second, "Manufacturer" given my ManagementObject with FTDI.
The code is:
public class FtdiDevice
{
public string ComPortName { get; set; }
}
public class usbState
{
public static List<FtdiDevice> existingFtdiPorts = new List<FtdiDevice>();
public static List<string> allComPorts = new List<string>();
public event EventHandler<MyEventArgs> DeviceAttached;
public event EventHandler<MyEventArgs> DeviceRemoved;
public usbState()
{
}
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
string[] updatedAddedComPorts = SerialPort.GetPortNames();
string[] result = updatedAddedComPorts.Except(allComPorts).ToArray();
allComPorts.Add(result[0]);
ManagementObjectCollection ManObjReturn;
ManagementObjectSearcher ManObjSearch;
ManObjSearch = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
ManObjReturn = ManObjSearch.Get();
foreach (ManagementObject ManObj in ManObjReturn)
{
int s = ManObj.Properties.Count;
string name = ManObj["Name"].ToString();
string man = ManObj["Manufacturer"].ToString();
if (string.Equals(man, "FTDI") && name.Contains(result[0]))
{
existingFtdiPorts.Add(new FtdiDevice() { ComPortName = result[0] });
DeviceAttached(this, new MyEventArgs() { ComPort = result[0] });
break;
}
}
}
private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
string[] updatedRemovedComPorts = SerialPort.GetPortNames();
string[] result = allComPorts.Except(updatedRemovedComPorts).ToArray();
allComPorts.Remove(result[0]);
var item = existingFtdiPorts.Find(x => x.ComPortName == result[0]);
if (item != null)
{
existingFtdiPorts.Remove(item);
DeviceRemoved(this, new MyEventArgs() { ComPort = result[0] });
}
}
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
}
class Program
{
static void NewDeviceAdded(object source, MyEventArgs e)
{
Console.WriteLine("New Device Attached at Port : " + e.ComPort);
}
static void DeviceRemoved(object source, MyEventArgs e)
{
Console.WriteLine("Device Removed at Port : " + e.ComPort);
}
static void Main(string[] args)
{
usbState.allComPorts = SerialPort.GetPortNames().ToList();
usbState usb = new usbState();
usb.DeviceAttached += NewDeviceAdded;
usb.DeviceRemoved += DeviceRemoved;
ManagementObjectCollection ManObjReturn;
ManagementObjectSearcher ManObjSearch;
ManObjSearch = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
ManObjReturn = ManObjSearch.Get();
foreach (ManagementObject ManObj in ManObjReturn)
{
for(int x = 0; x < usbState.allComPorts.Count; x++)
{
string name = ManObj["Name"].ToString();
string man = ManObj["Manufacturer"].ToString();
if (string.Equals(man, "FTDI") && name.Contains(usbState.allComPorts[x]))
{
usbState.existingFtdiPorts.Add(new FtdiDevice() { ComPortName = usbState.allComPorts[x] });
break;
}
}
}
BackgroundWorker bgwDriveDetector = new BackgroundWorker();
bgwDriveDetector.DoWork += usb.backgroundWorker1_DoWork;
bgwDriveDetector.RunWorkerAsync();
bgwDriveDetector.WorkerReportsProgress = true;
bgwDriveDetector.WorkerSupportsCancellation = true;
// System.Threading.Thread.Sleep(100000);
Console.ReadKey();
}
}
MyEventArgs class is:
public class MyEventArgs : EventArgs
{
public string ComPort { get; set; }
}
I have a problem detecting portable devices, specifically samsung phone or iphone.
I need to develop a program that will start once the detection of a portable plug-in and stop, once plugged out.
I've been trying this code, but only works with usb devices with storage, and not on portable device.
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
please help. thanks
Have you tried this:
System.IO.DriveInfo [] drives = System.IO.DriveInfo.GetDrives ();
foreach (System.IO.DriveInfo drive in drives)
{
if (drive.DriveType == DriveType.Removable)
{
Console.WriteLine ("Found removable drive {0}", drive.Name);
}
}
For More about DriveInfo
I want my application will show on my form my class properties so I started my class with BackgroundWorker and create ProgressChanged.
my class:
public class DumpFile
{
PacketDevice _device;
public int _packetsCount;
public double _bitsPerSecond;
public double _packetsPerSecond;
public DateTime _lastTimestamp;
public delegate void dlgPackProgress(int progress);
public event dlgPackProgress evePacketProgress;
public DumpFile(PacketDevice device, string pcapPath)
{
_device = device;
_pcapPath = pcapPath;
_packetsCount = 1;
}
public void startCapturing()
{
OnPacketProgress(_packetsCount++);
using (PacketCommunicator communicator = _device.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000)) //open the device
{
ThreadStart starter = delegate { openAdapterForStatistics(_device); };
new Thread(starter).Start();
using (PacketDumpFile dumpFile = communicator.OpenDump(_pcapPath)) //open the dump file
{
communicator.ReceivePackets(0, dumpFile.Dump); //start the capture
}
}
}
private void OnPacketProgress(int packet)
{
var handler = evePacketProgress;
if (handler != null)
{
handler(packet);
}
}
public void openAdapterForStatistics(PacketDevice selectedOutputDevice)
{
using (PacketCommunicator statCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000)) //open the output adapter
{
ThreadStart start = delegate { test(selectedOutputDevice); };
new Thread(start).Start();
statCommunicator.SetFilter("tcp"); //compile and set the filter
statCommunicator.Mode = PacketCommunicatorMode.Statistics; //put the interface in statstics mode
statCommunicator.ReceiveStatistics(0, StatisticsHandler);
}
}
public void test(PacketDevice selectedOutputDevice)
{
using (PacketCommunicator communicator = selectedOutputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
communicator.ReceivePackets(0, PacketHandler);
}
}
private void PacketHandler(Packet packet)
{
string result = _packetsCount.ToString() + ". " + packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Length;
_packetsCount++;
}
private void StatisticsHandler(PacketSampleStatistics statistics)
{
DateTime currentTimestamp = statistics.Timestamp; //current sample time
DateTime previousTimestamp = _lastTimestamp; //previous sample time
_lastTimestamp = currentTimestamp; //set _lastTimestamp for the next iteration
if (previousTimestamp == DateTime.MinValue) //if there wasn't a previous sample than skip this iteration (it's the first iteration)
{
return;
}
double delayInSeconds = (currentTimestamp - previousTimestamp).TotalSeconds; //calculate the delay from the last sample
_bitsPerSecond = statistics.AcceptedBytes * 8 / delayInSeconds; //calculate bits per second
_packetsPerSecond = statistics.AcceptedPackets / delayInSeconds; //calculate packets per second
}
}
start button who start capturing:
private void btnStartCapture_Click(object sender, EventArgs e)
{
timerSniffer.Start();
btnStartTabSniffer.Enabled = false;
btnStopTabSniffer.Enabled = true;
groupBoxSelectTabSniffer.Enabled = false;
bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWSniffer_ProgressChanged);
bgWorker.DoWork += new DoWorkEventHandler(
(s3, e3) =>
{
DumpFile dumpFile = new DumpFile(deviceForCapturing, pcapFilePathSniffer);
tshark.evePacketProgress += new DumpFile.dlgPackProgress(
(packet) =>
{
bgWorker.ReportProgress(packet, dumpFile);
});
dumpFile.startCapturing();
});
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s3, e3) =>
{
groupBoxSelectTabSniffer.Enabled = true;
});
bgWorker.RunWorkerAsync();
}
ProgressChanged:
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var dumpFile = (DumpFile)e.UserState;
lblNumberOfPacketsTabSniffer2.Text = dumpFile._packetsCount.ToString("#,##0");
lblTrafficRateTabSniffer2.Text = (dumpFile._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + dumpFile._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRateTabSniffer2.Text = dumpFile._packetsPerSecond.ToString("#,##0") + " Packets/sec";
}
the problem is that my application "get into" ProgressChanged functions but only in one time.
I think I missed something in my class.
I can only find one call to OnPacketProgress(), and it's outside of any loop.
public void startCapturing()
{
OnPacketProgress(_packetsCount++);
....
}
So Yes, that will only be called once.
You need something inside ReceivePackets()