Detecting Ethernet Port insertion/removal in my winforms application? - c#

I would like to detect when a device is connected to an ethernet port of the machine that my application is running on. I know how to do this with a USB port but the problem is, the Port isn't USB!
If it was a USB device I would simply override WndProc and catch the message, if it is WM_DEVICECHANGE, then i'm on to a winner, I was wondering if it was as simple as this with any device that may be plugged into the port?
I don't want to know if there is anything happening, or if the device is working, just simply to find if there has been an insertion or removal.

I never used it myself, but I think that the NetworkChange.NetworkAvailabilityChanged event might fit your needs.
Update
A brief investigation indicates that NetworkChange.NetworkAddressChanged might work better:
public static void Main()
{
NetworkChange.NetworkAddressChanged += (s, e) =>
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (var item in nics)
{
Console.WriteLine("Network Interface: {0}, Status: {1}", item.Name, item.OperationalStatus.ToString());
}
};
string input = string.Empty;
while (input != "quit")
{
input = Console.ReadLine();
}
}

I'm not sure if that's exactly suited for your needs, but you could have a look at the System.Net.NetworkInformation.NetworkChange class, which has 2 events that you could use :
NetworkAddressChanged
NetworkAvailabilityChanged
In the event handler, you can check whether the network interface involved is an Ethernet port

The NetworkChange class provides you with a NetworkAvailabilityChanged event triggered when interfaces switch from down to up or vice versa. Possibly not as low level as you might be looking for but you aren't specific in your objective in tracking this event.

Related

How to check if a Serial port is disconnected in c#

I want to check if a Serial port is disconnected or not after clicking a button in C# WinForms.
Eg:
private void btn_Click()
{
if("code to check device disconnected")
{
Do this;
}
else
{
Do this;
}}
PS: Is there any way to check that the device is disconnected when the application is running.
SerialPinchanged, ErrorRecieved, DataRecieved don't help.
Thank you in advance
It depends on the specifications of the target device connected to the COM port.
For example, if RTS/CTS or DTR/DSR are cross-connected, or if the device equivalent to a modem has a DCD or RI valid signal line, and the CTS/DSR/DCD/RI signal line shows valid connection information. , There may be a case where there is a command/response specification for health check or keep alive.
As an alternative, if the COM port is a USB Serial converter, you can check whether or not the device with the corresponding VID and PID exists, but make sure that the device is actually connected at the end of the converter. There is no guarantee.
It is simple logic that whenever SerialPort is disconnected, serialPort.IsOpen turns to false.
private void btn_Click()
{
if(!SerialPort.IsOpen)//If SerialPort is not open
{
Do this;
}
else//Else if SerialPort is open
{
Do this;
}
}

How can I get pid vid of a usb when it is plugged in?

I coded with c# in visual studio, windows form application. I want to see pid and vid of a USB when ıt is plugged in. I wrote this code but there is an error in foreach (ManagementObject service in s.Get()). In s.Get() part. It runs in Form1_Load part but it gets stuck in WNDProc.
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if(m.Msg == WM_DEVICECHANGE)
switch ((int)m.WParam)
{
case DBT_DEVICEARRIVAL:
listBox1.Items.Add("New Device Connected");
ManagementObjectSearcher s = new ManagementObjectSearcher("#SELECT * FROM Win32_USBHub");
foreach (ManagementObject service in s.Get())
{
listBox1.Items.Add(service);
}
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
foreach (string port in ports)
{
Console.WriteLine(port);
listBox1.Items.Add(port);
}
break;
case DBT_DEVICEREMOVECOMPLETE:
listBox1.Items.Add("Device Removed");
break;
}
The main issue is that the WM_DEVICECHANGE only comes for information you registered, with a few exceptions as can be read in the remarks of RegisterDeviceNotification.
Here are the details what you need to do:
To get the WM_DEVICECHANGE with DBT_DEVICEARRIVAL for devices, you need to call the Win32 API in user32.dll called RegisterDeviceNotification with a correctly filled DEV_BROADCAST_DEVICEINTERFACE_W struct.
If done so correctly you will get WM_DEVICECHANGE messages, which contain the event type (in our case DBT_DEVICEARRIVAL) as described in the Device Management Events, and a pointer to details. The pointer needs to be read as the DEV_BROADCAST_HDR struct , allowing you to recognise if this is indeed the DEV_BROADCAST_DEVICEINTERFACE_W struct. If so this struct will contain a name, which you will need to parse at it contains the VID & PID.
That is quite a lot to process, and it took me a couple of hours to get it right. If you need a quick solution, and skip implementing the horrible details, add the NuGet package Dapplo.Windows.Messages (VID & PID are available with 0.9.7 and later) to your project. Use the following code only once, otherwise your code will be called multiple times, there is no need to do this from a Window but it must be from a Windows Forms or WPF application:
var deviceNotificationSubscription = DeviceNotification
.OnDeviceArrival()
.Subscribe(deviceInterfaceChangeInfo => {
// Your code goes here, and will be automatically called
var vid = deviceInterfaceChangeInfo.Device.VendorId;
var pid = deviceInterfaceChangeInfo.Device.ProductId;
});
My library highly depend on System.Reactive, I won't go into details here, which allows a more functional approach to your application. You can stop receiving the events by calling deviceNotificationSubscription.Dispose(); The library creates it's own hidden message window to receive the window messages, so you can even continue receiving the information in the background.
The Device property of the DeviceInterfaceChangeInfo has the DevBroadcastDeviceInterface struct, which contains the original Win32 information, but additionally has some higher level properties like:
a friendly name, which is retrieved from the registry
device type like USB, HID etc including an IsUSB
vendor ID
product ID
a DeviceInterfaceClass enum for easier code access to the class
a generated URL to get more information on the device
Let me know if this works and helps here by and if you have any questions raise an issue on my Dapplo.Windows GitHub project! There is a lot more in this library but unfortunately most documentation still needs writing.

How get the serial port name of an Arduino

I'm trying to figure out which serial port belongs to an Arduino.
Since the SerialPort class does not reveal any information about
the underlying hardware, I'm trying to use LibUsbDotNet instead.
Using the following code to get a list of all devices:
UsbDevice.ForceLibUsbWinBack = true;
var devices = UsbDevice.AllDevices;
I can then either iterate over all of them or search for the Arduino specifically:
var deviceFinder = new UsbDeviceFinder(0x2341, 0x8036);
var arduino = devices.Find(deviceFinder);
This actually works and I get an instance of UsbRegistry,
but I'm unable to open the device or determine through which serial port it is exposed.
USBDevice arduinoUsbDevice;
usbRegistry.Open(out arduinoUsbDevice);
Since this doesn't work arduinoUsbDevice remains null.
I then tried using the DeviceNotifier class which raises an event whenever
a device is added or removed from the system:
var notifier = DeviceNotifier.OpenDeviceNotifier();
notifier.OnDeviceNotify += (s, e) =>
{
WriteLine(e.Device?.Name ?? "no device");
WriteLine(e.Device?.IdProduct ?? 0);
WriteLine(e.Device?.IdVendor ?? 0);
WriteLine(e.EventType);
WriteLine(e.Object);
WriteLine(e.Port?.Name ?? "");
};
Now whenever I connect the Arduino to the computer, the event is raised twice.
As if two separate devices are being connected,
but only one of them is ever returned by UsbDevice.AllDevices:
` \\?\USB#VID_2341&PID_8036#7&533912d&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
32822
9025
DeviceArrival
FullName:USB#VID_2341&PID_8036#7&533912d&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Vid:0x2341
Pid:0x8036
SerialNumber:7&533912d&0&2
ClassGuid:a5dcbf10-6530-11d2-901f-00c04fb951ed
no device
0
0
DeviceArrival
[Port Name:COM5]
COM5
The first time the event is raised for the device we could find before as well.
The second time it is raised with e.Device set to null but
with e.Port set to COM5, which is the information I'm after.
So the problem is I can only get this information when the Arduino is connected
after the software has been started and even then linking the two events is
kind of a guessing game.
Is there any way of getting the information without having to rely
on the events raised by the DeviceNotifier class?
I'm aware I could use System.Management and WMI queries, but
these are not available on Linux and MacOS, which is why I'm using
LibUsbDotNet instead.
The native library I'm using is libusb-1.0

Can my soft be noticed of a change in the Windows Certificate Store ? (.NET)

As the title suggests, I want to know if there is some kind of event to catch to know when Certificate Store has changed.
The goal is to detect when a user entered a specific kind of USB smartcard / stick with a signing certificate/token in it. The certificate are registered in the Windows Cert Store, ("My", personnal certificates).
I don't like the idea of detecting USB events, because there is a variable delay between the moment when the key is plugged and the moment the certificate is actually registered (and usable).
Of course, I can always set a timer that checks the store every 10 sec or so, but I hope you'll agree that it is a not elegant solution. Of course if no other good option is available, that's what I'll end up doing I guess.
Thank you
How about a hybrid approach? Watch for USB events, then when a USB key is plugged in, start polling the store every couple of seconds until you see the new cert. Still not ideal, but much closer to it than a dumb poll every ten seconds, 24/7/365.
The trick will be knowing when the USB key is of the particular type that would end up registering a certificate. If you can know this in the USB event handler, then check for it, and if the user plugs in an ordinary flash drive, don't start polling. If you can't know this, then when you detect a new connection, you might only poll the certificate store for a minute before giving up.
I have the same problem.
I temporarily solved it by waiting until the smart card is no longer shared with another process (the Certificate Propagation Service). Not very nice and the robustness is also questionable, but it works for now.
In C#:
string selector = SmartCardReader.GetDeviceSelector();
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);
foreach (DeviceInformation device in devices)
{
SmartCardReader reader = await SmartCardReader.FromIdAsync(device.Id);
reader.CardAdded += ReaderOnCardAdded;
}
private static void ReaderOnCardAdded(SmartCardReader sender, CardAddedEventArgs args)
{
Task t = ReaderOnCardAddedAsync(sender, args);
t.Wait();
}
private static async Task ReaderOnCardAddedAsync(SmartCardReader sender, CardAddedEventArgs args)
{
SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(args.SmartCard);
SmartCardStatus status;
do
{
status = await provisioning.SmartCard.GetStatusAsync();
Thread.Sleep(100);
} while (status == SmartCardStatus.Shared);
PrintCertificatesOrDoSomethingElseUseful();
}
Anyone with a better solution?

C# NetworkAvailabilitychangedEvent

VS 2008
I am developing an application that has to detect whether a client has a network connection. i.e. LAN cable plugged in or wireless switched on. I have been using the code below.
I am using the NetworkAvailabilitychangedEvent to fire an event when their wireless is turned off or the cable has been pulled out. However, this only works if the user has only 3 connections present (LAN, Wireless, and loopbacks).
Microsoft: "The network is available when at least one network interface is marked "up" and is not a tunnel or loopback interface".
However, some client has more than 3 connections. One client had a bluetooth connection and someone else had some VMWare connections. On these client it failed to fire the event.
Is there anyway I can ignore all these connections I am not interested in listening out for, and just listen on the LAN and Wireless?
Many thanks for any advice,
private void Form1_Load(object sender, EventArgs e)
{
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(OnNetworkChangedEvent);
}
private void OnNetworkChangedEvent(object sender, NetworkAvailabilityEventArgs e)
{
bool available = e.IsAvailable;
NetworkInterface[] networkConnections = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface ni in networkConnections)
{
if (ni.Name == "Local Area Connection")
{
if (ni.OperationalStatus == OperationalStatus.Down)
{
Console.WriteLine("LAN disconnected: " + ni.Description);
}
}
else if (ni.Name == "Wireless Network Connection")
{
if (ni.OperationalStatus == OperationalStatus.Down)
{
Console.WriteLine("Wireless disconnected: " + ni.Description);
}
}
}
}
Perhaps you need to implement some sort of polling agent that runs on a seperate thread and regularly tries to contact something listening on a remote server (or servers?).
When it fails (or perhaps when a preset number of connection attempts fail) then fire an event. Same when it goes from a fail-succeed state.
Your application would subscribe to these events and take action accordingly.
Of course this may not be suitable for your scenario..

Categories

Resources