MSNdis_StatusMediaDisconnect and device Unique Name - c#

I'm using ManagementEventWatcher to watch the disconnection of network cable using System.Management.
ManagementEventWatcher with the WQL: SELECT * FROM MSNdis_StatusMediaDisconnect,
and the following method is fired, when EventArrived:
private void ServiceNetWorkStatusWmiDisconnected(object sender, EventArrivedEventArgs args)
{
string instanceName = args.NewEvent.Properties["InstanceName"].Value as string;
ServiceNetWorkStatusWmi = string.Format("Network disconnected ({0})", instanceName);
Console.WriteLine(ServiceNetWorkStatusWmi);
}
The problem is:
I have 2 network interfaces, from the same manufacturer , and both case, the InstanceName has the same value and I can´t identify what network unplugged!
I have tried all properties from EventArrivedEventArgs, but they don´t have a constraint id for device... like an Device Id.
How can I find out witch network interface was unplugged?

Have a look to the "Win32_NetworkAdapter.NetConnectionID". This is - at my machine [!!] - the excact same string you'll see in the network connections [control panel] and it should be the same value, apearing in "MSNdis_EnumerateAdapter.InstanceName=".
May be, this helps!?
br--mabra

Related

Filter for serial ports

I have an application in which I have to use the serial ports, so alright, it finds all right, but I thought and if the client has more than 1 COM port connected on the PC? How do I do when I checkbox and dial, when updating only my device appears? (My USB converter is no longer generic, it contains your own name and address).
Here is the function where I update the COM ports
public void AtualizarPortas()
{
PortasDisponiveis.Clear();
var portas = SerialPort.GetPortNames().OrderBy(x => x).ToList();
foreach (var porta in portas)
{
PortasDisponiveis.Add(porta);
}
PortaSelecionada = PortasDisponiveis.FirstOrDefault();
}
What could I do to get only my device to appear?

Async HFP discovery with 32feet

I am in the process of writing a bluetooth scanner to monitor traffic outside my house. I understand that car BT devices generally have 3 states, visible (always on), limited, and invisible.
I'm using asynchronous device discovery with the Bluesoleil drivers, and a Class 1 Bluetooth dongle.
My problem is the device name and device class isn't being discovered. It is discovering the device address, and the range, but not the name of the device.
I have tried using System.Threading.Thread.Sleep(1000) then calling device.Refresh() to no avail.
It is picking up the name of a few things that are in range, like TVs, and Fitbit Flexes, but it's important that I can find the name and CoD of the car bluetooth devices, not just the MAC address and the range.
public void SetupListener()
{
var client = new BluetoothClient();
var component = new BluetoothComponent(client);
component.DiscoverDevicesAsync(255, false, false, true, false, null);
component.DiscoverDevicesProgress += component_DiscoverDevicesProgress;
component.DiscoverDevicesComplete += component_DiscoverDevicesComplete;
}
void component_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e)
{
SetupListener();
}
void component_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
{
BluetoothDeviceInfo[] availableDevices = e.Devices as BluetoothDeviceInfo[];
foreach (BluetoothDeviceInfo device in availableDevices)
{
device.Refresh();
var name = device.DeviceName; // This mostly returns the MAC address
var cod = device.ClassOfDevice.Device; // This mostly returns Miscellaneous
}
}
The application I've built is a simple WPF form that dumps the found devices to a datagrid (which I've removed from the code for simplicity's sake). This is generally what the results look like.
When I sit outside closer to the road, it is definitely picking up more and more devices as cars drive by, but I can't tell what type of device it's detecting.
Any help would be greatly appreciated.

Detect when ethernet cable is plugged

I'm trying to detect when an Ethernet cable is plugged-in or unplugged but i have some probleme and i don't know if i'm doing this good or not.
I'm using NetworkChange.NetworkAddressChanged
to detect when the network change
and then NetworkInterface.GetAllNetworkInterfaces() for checking if Ethernet connexion is available or not with the property .OperationalStatus.
But when i search for the Ethernet connexion in all the network interfaces, it return me what i'm looking for, but it always return me the Bluetooth connection with it.
Here is the code :
public Form1()
{
InitializeComponent();
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedCallback);
Console.ReadLine();
}
static void AddressChangedCallback(object sender, EventArgs e)
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface myInterface in adapters)
{
//if (n.Description.ToLower().Contains("ethernet")){
//if (n.NetworkInterfaceType.ToString().ToLower().Contains("ethernet")){
IPInterfaceProperties properties = n.GetIPProperties();
if (myInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
Console.WriteLine(myInterface.Description + " ........... : " + myInterface.OperationalStatus);
Console.WriteLine("NetworkInterfaceType : " + myInterface.NetworkInterfaceType);
}
}
}
At the beginning, i was trying to check the name of the connection and looks if contains the "Ethernet" word, but it appears (if i'm not wrong) sometimes the connection name does not contain "Ethernet".
Do you have some tips for always bring the good connection (without the bluetooth)?
Am i wrong in my approach?
I'm testing it on a Surface Pro 3... but maybe i have the Bluetooth problem because of that?
Despite that, i need it to work even on device like this.
This can be done by checking its operational status as:
foreach (System.Net.NetworkInformation.NetworkInterface net in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
{
if (net.OperationalStatus ==
System.Net.NetworkInformation.OperationalStatus.Up)
Console.WriteLine("N/w connected");
else
Console.WriteLine("N/w not connected");
}
This links shows how to do it with Powershell, but one of the cases uses WMI.
http://www.powershellmagazine.com/2013/04/04/pstip-detecting-wi-fi-adapters/
And this links shows a interesting property that can help sometimes:
https://msdn.microsoft.com/en-us/library/aa394217(v=vs.85).aspx
GatewayCostMetric
Data type: uint16 array
Access type: Read-only Array
of integer cost metric values (ranging from 1 to 9999) to be used in
calculating the fastest, most reliable, or least resource-intensive
routes. This argument has a one-to-one correspondence with the
DefaultIPGateway property.

Unable to get the IP Address of network printer?

I need to find the IP address of the installed printers on my laptop. I move my laptop between different locations and networks. Each network has its own set of ip addresses. The laptop has different printers installed for each location with all connections being made wirelessly.
In using the below code (.net 4.0), the QueuePort.Name returns:
WSD-27e3f972-cdc7-459d-b0c1-20e8410fb1db.0032 and
192.168.1.12_1
Since these are network printers, I assume these have to resolve to a real IP Address??
Where am I going wrong? Or is there a better way? Any help is really appreciated.
IEnumerable<Printer> GetLocalPrinters()
{
EnumeratedPrintQueueTypes[] enumerationFlags = { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections };
LocalPrintServer printServer = new LocalPrintServer();
var x = printServer.GetPrintQueues(enumerationFlags).Select(y =>
new Printer
{
Fullname = y.FullName,
QueuePortName = y.QueuePort.Name,
Location = y.Location
})
.OrderBy( z => z.QueuePortName);
return x;
}
The portname is NOT the IP address. Sometimes they are the same text.
They answer appears to be here:
Determine the IP Address of a Printer in C#
Edited 31-Oct-2011:
Query the WMI for the printer port IP address.
using System;
using System.Management;
namespace WMI_example_01
{
class Program
{
static void Main(string[] args)
{
var scope = new ManagementScope(#"\\.\root\cimv2");
var query = new ObjectQuery("SELECT * FROM win32_tcpipprinterport");
var searcher = new ManagementObjectSearcher(scope, query);
var collection = searcher.Get();
foreach(var col in collection)
{
Console.WriteLine("Port name: {0}\tHostAddress: {1}", col["Name"], col"HostAddress"]);
}
}
}
}
The printing queue has a corresponding port that is handled by the port monitor.
There are different port monitors (not only standard monitors like TCPMON and WSD but also custom and vendor-specific), as far as I know, there is no universal way to deal with all kinds of them.
From the provided port name, I assume you are dealing with the WSD port. Here things become a bit tricky, I suggest you read my answer https://stackoverflow.com/a/63705944/4700228 for the solution.

How can I find out a COM port number of a bluetooth device in c#?

My company developed a device that communicates with a PC via Bluetooth using a virtual COM port.
Now we need a user to pair a device with a PC (MS Windows OS) first and then enter it's com port number manually into our application(I bet 95% of users will fail on this taks).
So I'd like my application to present a user with a list of paired bluetooth devices (a list of their "friendly names") and after that I'd like to find out the selecded device's COM port number automatically.
How can I do it in c#? (a solution independent of installed bluetooth stack is appreciated).
Thanks in advance.
See my answer at Widcomm bluetooth : how to open the virtual COM for my understanding of the licence: using the binary version is free for commercial use. And, also that I'm maintainer of the library.
So a brief slight digression. I'm not a big fan of virtual COM ports. It always seems much easier to use a direct 'sockets' connection, rather than attempt to setup a COM port, and try to find what name it was created as (see below!), and then have to open a SerialPort to use it, and then if the connection is lost one doesn't know and have simply to keep retrying... With the library its so much easier to just to create and use that direct Bluetooth connection!
However you may want a solution to your current task at the moment. :-) So, use WMI to find the current COM ports in place and see if any of them are for your device. For example in PowerShell:
C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"
...
...
DeviceID : COM66
PNPDeviceID : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519_C00000003
In that big long string one sees the address of the target device: 00803A686519. One can use WMI from .NET, run that query, filter the ones with "BTHENUM", and then parse out the address.
If you the do need to create a new Bluetooth virtual COM port, use 32feet.NET's BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort) API. See the "Bluetooth Serial Ports" section in the User Guide e.g. at http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html, and the class documentation in the release.
Unfortunately the native Win32 API we call does not tell what name of COM port it created! :-( So run the WMI query before and after the call to see what new name appeared (or use System.IO.Ports.SerialPort.GetPortNames as its simpler).
That's all specific to the Microsoft Bluetooth stack. I haven't investigated how other stacks behave in this regard. After a brief check Widcomm's serial ports appear in SerialPort.GetPortNames but not in the WMI query...
First, create a Management Object Searcher to search the WMI database:
ManagementObjectSearcher serialSearcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_SerialPort");
Next, use LINQ to get all the serial ports into a query:
var query = from ManagementObject s in serialSearcher.Get()
select new { Name = s["Name"], DeviceID = s["DeviceID"], PNPDeviceID = s["PNPDeviceID"] }; // DeviceID -- > PNPDeviceID
You can now print all the COM ports, their friendly names and you can even filter through their PNPDeviceID's to find the bluetooth device address. Here's an example:
foreach (var port in query)
{
Console.WriteLine("{0} - {1}", port.DeviceID, port.Name);
var pnpDeviceId = port.PNPDeviceID.ToString();
if(pnpDeviceId.Contains("BTHENUM"))
{
var bluetoothDeviceAddress = pnpDeviceId.Split('&')[4].Split('_')[0];
if (bluetoothDeviceAddress.Length == 12 && bluetoothDeviceAddress != "000000000000")
{
Console.WriteLine(" - Address: {0}", bluetoothDeviceAddress);
}
}
}
I manage to get the bluetooth name and the COM port by fiddling the registry key
The pseudo code to obtain the bluetooth information is below:
enumerate all the COM port available in the PNP
obtain the device classGuid
search the bluetooth address from the classGuid
when the bluetooth address is known, the bluetooth name can be obtained from the this registry SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices
The code is below, just call the GetBluetoothPort(), it will return a list of bluetooth devices, and you could connect them by passing the COM port number to the SerialPort class
public static string[] GetBluetoothPort()
{
Regex regexPortName = new Regex(#"(COM\d+)");
List<string> portList = new List<string>();
ManagementObjectSearcher searchSerial = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity");
foreach (ManagementObject obj in searchSerial.Get()) {
string name = obj["Name"] as string;
string classGuid = obj["ClassGuid"] as string;
string deviceID = obj["DeviceID"] as string;
if (classGuid != null && deviceID != null) {
if (String.Equals(classGuid, "{4d36e978-e325-11ce-bfc1-08002be10318}", StringComparison.InvariantCulture)) {
string[] tokens = deviceID.Split('&');
if (tokens.Length >= 4) {
string[] addressToken = tokens[4].Split('_');
string bluetoothAddress = addressToken[0];
Match m = regexPortName.Match(name);
string comPortNumber = "";
if (m.Success) {
comPortNumber = m.Groups[1].ToString();
}
if (Convert.ToUInt64(bluetoothAddress, 16) > 0) {
string bluetoothName = GetBluetoothRegistryName(bluetoothAddress);
portList.Add(String.Format("{0} {1} ({2})", bluetoothName, bluetoothAddress, comPortNumber));
}
}
}
}
}
return portList.ToArray();
}
private static string GetBluetoothRegistryName(string address)
{
string deviceName = "";
string registryPath = #"SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices";
string devicePath = String.Format(#"{0}\{1}", registryPath, address);
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(devicePath)) {
if (key != null) {
Object o = key.GetValue("Name");
byte[] raw = o as byte[];
if (raw != null) {
deviceName = Encoding.ASCII.GetString(raw);
}
}
}
return deviceName;
}
Maybe it is not what you are looking for, and maybe you already found your answer...
I just found a question not exactly like yours but worked for me.. With this one you can find out which one of your COM Ports are from a Bluetooth device:
StackOverflow - Determine if serial port is normal COM or SPP
I hope it helps somehow. If you find out how to do what you wanted, please let me know. Thanks.
So, to get the information about a remote device including its name, using 32feet.NET do:
BluetoothAddress addr = ... ...
BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr);
string name = info.DeviceName;
If not using the library you'll have to P/Invoke Win32's BluetoothGetDeviceInfo.
private static string FindSerialPortForRFIDReaderCore()
{
string serialPort = "";
List<string> ports = new List<string>();
System.Management.ManagementObjectSearcher Searcher = new System.Management.ManagementObjectSearcher("Select * from WIN32_SerialPort");
foreach (System.Management.ManagementObject Port in Searcher.Get())
{
if (Port["PNPDeviceID"].ToString().ToUpper().Contains("MacAddress"))
ports.Add(Port["DeviceID"].ToString());
}
if (ports.Count > 1) // There are more than one Serial Ports created for the bluetooth device.
serialPort = ports.OrderByDescending(p => p).FirstOrDefault();
else if(ports.Count == 1)
serialPort = ports[0];
return serialPort;
}

Categories

Resources