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; }
}
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 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 have an application that scans the local network for connected PC's.
I want to get the client information (IP address, MAC address, Host name...) and the connection state (download rate, upload rate), and put them in the ListView, but the problem is that this information is not constant!
How could I get this information in real time? The info in the ListView changes every time the info of the client changes?
My current code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using NetUtils;
using System.Net;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
private IPScanner _scanner;
private class HostSorterByIP : IComparer
{
public int Compare(object x, object y)
{
byte[] bytes1 = ((IPScanHostState)((ListViewItem)x).Tag).Address.GetAddressBytes();
byte[] bytes2 = ((IPScanHostState)((ListViewItem)y).Tag).Address.GetAddressBytes();
int i = bytes1.Length - 1;
for (; i > 0 && bytes1[i] == bytes2[i]; i--)
;
return bytes1[i] - bytes2[i];
}
}
public Form1()
{
InitializeComponent();
_scanner = new IPScanner((int)_spnConcurrentPings.Value, (int)_spnPingsPerScan.Value, _cbContinuousScan.Checked,
(int)_spnTimeout.Value, (int)_spnTTL.Value, _cbDontFragment.Checked, (int)_spnBufferSize.Value);
_scanner.OnAliveHostFound += new IPScanner.AliveHostFoundDelegate(_scanner_OnAliveHostFound);
_scanner.OnStartScan += new IPScanner.ScanStateChangeDelegate(_scanner_OnStartScan);
_scanner.OnStopScan += new IPScanner.ScanStateChangeDelegate(_scanner_OnStopScan);
_scanner.OnRestartScan +=new IPScanner.ScanStateChangeDelegate(_scanner_OnRestartScan);
_scanner.OnScanProgressUpdate +=new IPScanner.ScanProgressUpdateDelegate(_scanner_OnScanProgressUpdate);
_lvAliveHosts.ListViewItemSorter = new HostSorterByIP();
_cmbRangeType.SelectedIndex = 0;
}
private void _scanner_OnAliveHostFound(IPScanner scanner, IPScanHostState host)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.AliveHostFoundDelegate(_scanner_OnAliveHostFound), scanner, host);
return;
}
ListViewItem item = new ListViewItem();
item.Tag = host;
item.BackColor = Color.GreenYellow;
item.SubItems.Add(host.Address.ToString());
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
_lvAliveHosts.Items.Add(item);
_lvAliveHosts.Sort();
host.OnHostNameAvailable += new IPScanHostState.HostNameAvailableDelegate(host_OnHostNameAvailable);
host.OnStateChange += new IPScanHostState.StateChangeDelegate(host_OnStateChange);
if (!host.IsTesting())
{
item.ImageIndex = (int)host.QualityCategory;
item.SubItems[2].Text = host.AvgResponseTime.ToString("F02") + " ms";
item.SubItems[3].Text = ((float)(host.LossCount) / host.PingsCount).ToString("P");
item.SubItems[4].Text = host.HostName;
}
//AddLogEntry("Host [" + host.Address.ToString() + "] is alive.");
Timer newTimer = new Timer();
newTimer.Tag = item;
newTimer.Interval = 2000;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Enabled = true;
}
void host_OnHostNameAvailable(IPScanHostState host)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanHostState.HostNameAvailableDelegate(host_OnHostNameAvailable), host);
return;
}
ListViewItem item = FindListViewItem(host);
if (item != null)
item.SubItems[4].Text = host.HostName;
}
private ListViewItem FindListViewItem(IPScanHostState host)
{
foreach (ListViewItem item in _lvAliveHosts.Items)
{
if (item.Tag == host)
return item;
}
return null;
}
private void host_OnStateChange(IPScanHostState host, IPScanHostState.State oldState)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanHostState.StateChangeDelegate(host_OnStateChange), host, oldState);
return;
}
if (!host.IsTesting())
{
ListViewItem item = FindListViewItem(host);
if (item != null)
{
if (host.IsAlive())
{
item.ImageIndex = (int)host.QualityCategory;
item.SubItems[2].Text = host.AvgResponseTime.ToString("F02") + " ms";
item.SubItems[3].Text = ((float)(host.LossCount) / host.PingsCount).ToString("P");
}
else
{
//AddLogEntry("Host [" + host.Address.ToString() + "] died.");
host.OnStateChange -= host_OnStateChange;
host.OnHostNameAvailable -= host_OnHostNameAvailable;
item.BackColor = Color.IndianRed;
Timer removeTimer = new Timer();
removeTimer.Tag = item;
removeTimer.Interval = 2000;
removeTimer.Tick += new EventHandler(removeTimer_Tick);
removeTimer.Enabled = true;
}
}
}
}
void newTimer_Tick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
timer.Tick -= newTimer_Tick;
ListViewItem item = (ListViewItem)timer.Tag;
item.BackColor = Color.White;
}
void removeTimer_Tick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
timer.Tick -= newTimer_Tick;
ListViewItem item = (ListViewItem)timer.Tag;
_lvAliveHosts.Items.Remove(item);
}
private void _scanner_OnStartScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnStartScan), scanner);
return;
}
foreach (ListViewItem item in _lvAliveHosts.Items)
{
((IPScanHostState)item.Tag).OnStateChange -= host_OnStateChange;
((IPScanHostState)item.Tag).OnHostNameAvailable -= host_OnHostNameAvailable;
}
_lvAliveHosts.Items.Clear();
_prgScanProgress.Value = 0;
EnableSettings(false);
}
private void EnableSettings(bool enable)
{
_cmbRangeType.Enabled = _tbRangeStart.Enabled = _tbRangeEnd.Enabled = _spnTimeout.Enabled = _spnTTL.Enabled = _spnBufferSize.Enabled = _cbDontFragment.Enabled =
_spnConcurrentPings.Enabled = _spnPingsPerScan.Enabled = _cbContinuousScan.Enabled = enable;
_btnStartStop.Text = enable ? "&Start" : "&Stop";
if (enable)
_prgScanProgress.Text = "Scanner is not running!";
}
private void _btnStartStop_Click(object sender, EventArgs e)
{
if (!_scanner.Active)
{
try
{
_scanner.Start(_cmbRangeType.SelectedIndex == 0
? new IPScanRange(IPAddress.Parse(_tbRangeStart.Text), IPAddress.Parse(_tbRangeEnd.Text))
: new IPScanRange(IPAddress.Parse(_tbRangeStart.Text), int.Parse(_tbRangeEnd.Text)));
}
catch (FormatException)
{
MessageBox.Show(this, "Cannot parse IP range or subnetmask!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
_scanner.Stop(false);
}
private void _scanner_OnStopScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnStopScan), scanner);
return;
}
EnableSettings(true);
_prgScanProgress.Value = 0;
}
void _scanner_OnRestartScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnRestartScan), scanner);
return;
}
_prgScanProgress.Value = 0;
}
void _scanner_OnScanProgressUpdate(IPScanner scanner, IPAddress currentAddress, ulong progress, ulong total)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanProgressUpdateDelegate(_scanner_OnScanProgressUpdate), scanner, currentAddress, progress, total);
return;
}
int prog = (int)((100 * progress) / total);
_prgScanProgress.Value = prog;
_prgScanProgress.Text = prog.ToString() + "%" + " [" + currentAddress.ToString() + "]";
}
private void _cmbRangeType_SelectedIndexChanged(object sender, EventArgs e)
{
if (_cmbRangeType.SelectedIndex == 0)
{
_lRangeSep.Text = "-";
_lRangeEnd.Text = "Range &End:";
_tbRangeEnd.Size = new Size(130, _tbRangeEnd.Size.Height);
}
else
{
_lRangeSep.Text = "/";
_lRangeEnd.Text = "Subnet &Mask:";
_tbRangeEnd.Size = new Size(32, _tbRangeEnd.Size.Height);
}
}
//private void _lvAliveHosts_DoubleClick(object sender, EventArgs e) { _btnAddHost_Click(sender, e); }
private void IPScanForm_FormClosing(object sender, FormClosingEventArgs e) { _scanner.Stop(true); }
private ListViewItem.ListViewSubItem _activeTooltipSubitem = null;
private static string[] QualityCategoryNames = { "Very Poor", "Poor", "Fair", "Good", "Very Good", "Excellent", "Perfect" };
private void _lvAliveHosts_MouseMove(object sender, MouseEventArgs e)
{
ListViewItem item = _lvAliveHosts.HitTest(e.Location).Item;
if (item != null)
{
ListViewItem.ListViewSubItem subitem = _lvAliveHosts.HitTest(e.Location).SubItem;
if (subitem != null && item.SubItems.IndexOf(subitem) == 0)
{
if (_activeTooltipSubitem != subitem)
{
_ttQuality.Show("Quality: " + QualityCategoryNames[item.ImageIndex], _lvAliveHosts, item.SubItems[1].Bounds.X, subitem.Bounds.Y);
_activeTooltipSubitem = subitem;
}
return;
}
}
_activeTooltipSubitem = null;
_ttQuality.Hide(_lvAliveHosts);
}
}
}
I would create the list of clients and show them in the listview.
Than, in a background thread, every X seconds, poll all of the current clients.
Next , compare the list of updated clients to a list of clients from last update.
What remain to do is to add any new client to the list, and remove any client which no longer exists.
Pay attention to the context, use InvokeRequired() to get access to the UI control from the background thread.
EDIT:
here is how to run a background thread:
static void Main(string[] args)
{
Thread worker = new Thread(DoBackgroundWork);
}
public static void DoBackgroundWork()
{
while (true)
{
//Sleep 10 seconds
Thread.Sleep(10000);
//Do some work and than post to the control using Invoke()
}
}
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()
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();
}
}
}