如何在c#中找到蓝牙设备的COM端口号?

我公司开发了一种使用虚拟COM端口通过蓝牙与PC通信的设备。

现在我们需要用户首先将设备与PC(MS Windows操作系统)配对,然后手动输入它的com端口号到我们的应用程序中(我敢打赌,95%的用户会因此而失败)。

所以我希望我的应用程序向用户提供配对蓝牙设备列表(他们的“友好名称”列表),之后我想自动找出被选中设备的COM端口号。

我怎么能在c#中做到这一点? (赞赏独立于安装的蓝牙堆栈的解决方案)。

提前致谢。

请参阅我在Widcomm蓝牙的回答:如何打开虚拟COM以了解我对许可的理解:使用二进制版本是免费的商业用途。 而且,我也是图书馆的维护者。

所以简短的小题外话。 我不是虚拟COM端口的忠实粉丝。 使用直接’套接字’连接似乎要容易得多,而不是尝试设置COM端口,并尝试找到它创建的名称(见下文!),然后必须打开一个SerialPort才能使用它,然后,如果连接丢失,则不知道并且只是继续重试…使用库更容易创建和使用直接蓝牙连接!

但是,您现在可能需要解决当前任务的问题。 :-)因此,使用WMI找到当前的COM端口,看看它们是否适用于您的设备。 例如在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 

在那个大的长字符串中,可以看到目标设备的地址:00803A686519。 可以使用.NET中的WMI,运行该查询,过滤带有“BTHENUM”的查询,然后解析出地址。

如果您确实需要创建新的蓝牙虚拟COM端口,请使用32feet.NET的BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort)API。 请参阅用户指南中的“蓝牙串行端口”部分,例如http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20–%20User%20Guide.html ,以及发布。

不幸的是,我们调用的本机Win32 API并没有告诉它创建的COM端口的名称! :-(因此,在调用之前和之后运行WMI查询以查看出现的新名称(或使用System.IO.Ports.SerialPort.GetPortNames作为其更简单)。

这些都是微软蓝牙堆栈特有的。 我还没有研究过其他堆栈在这方面的表现。 经过简单检查后,Widcomm的串口出现在SerialPort.GetPortNames中,但不出现在WMI查询中……

首先,创建一个管理对象搜索器来搜索WMI数据库:

 ManagementObjectSearcher serialSearcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_SerialPort"); 

接下来,使用LINQ将所有串行端口放入查询中:

 var query = from ManagementObject s in serialSearcher.Get() select new { Name = s["Name"], DeviceID = s["DeviceID"], PNPDeviceID = s["PNPDeviceID"] }; // DeviceID -- > PNPDeviceID 

您现在可以打印所有COM端口,它们的友好名称,您甚至可以通过其PNPDeviceID过滤来查找蓝牙设备地址。 这是一个例子:

 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); } } } 

我设法通过摆弄注册表项来获取蓝牙名称和COM端口

获取蓝牙信息的伪代码如下:

  • 枚举PNP中可用的所有COM端口
  • 获取设备classGuid
  • 从classGuid中搜索蓝牙地址
  • 当蓝牙地址已知时,可以从此注册表SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices获取蓝牙名称

代码如下,只需调用GetBluetoothPort(),它将返回蓝牙设备列表,您可以通过将COM端口号传递给SerialPort类来连接它们

 public static string[] GetBluetoothPort() { Regex regexPortName = new Regex(@"(COM\d+)"); List portList = new List(); 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; } 

也许这不是你想要的,也许你已经找到了答案……

我刚刚发现了一个与你不完全相同的问题,但为我工作..有了这个,你可以找到你的哪个COM端口来自蓝牙设备: StackOverflow – 确定串口是普通COM还是SPP

我希望它有所帮助。 如果您发现如何做您想做的事,请告诉我。 谢谢。

因此,要获取有关远程设备的信息(包括其名称),请使用32feet.NET:

 BluetoothAddress addr = ... ... BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr); string name = info.DeviceName; 

如果不使用该库,则必须使用P / Invoke Win32的BluetoothGetDeviceInfo。

  private static string FindSerialPortForRFIDReaderCore() { string serialPort = ""; List ports = new List(); 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; }