我们公司开发了一款通过虚拟COM端口使用蓝牙与PC通信的设备。
现在我们需要用户首先将设备与PC(运行MS Windows操作系统)配对,然后手动将其COM端口号输入到我们的应用程序中(我敢打赌95%的用户无法完成此任务)。
因此,我希望我的应用程序向用户展示已配对蓝牙设备的列表(它们的“友好名称”列表),然后自动查找所选设备的COM端口号。
如何在C#中实现此功能? (独立于安装的蓝牙堆栈的解决方案将不胜感激)。
提前致谢。
我们公司开发了一款通过虚拟COM端口使用蓝牙与PC通信的设备。
现在我们需要用户首先将设备与PC(运行MS Windows操作系统)配对,然后手动将其COM端口号输入到我们的应用程序中(我敢打赌95%的用户无法完成此任务)。
因此,我希望我的应用程序向用户展示已配对蓝牙设备的列表(它们的“友好名称”列表),然后自动查找所选设备的COM端口号。
如何在C#中实现此功能? (独立于安装的蓝牙堆栈的解决方案将不胜感激)。
提前致谢。
C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"
...
...
DeviceID : COM66
PNPDeviceID : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519_C00000003
首先,创建一个管理对象搜索器来搜索WMI数据库:
ManagementObjectSearcher serialSearcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_SerialPort");
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);
}
}
}
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;
}
也许这不是你要找的,也许你已经找到了答案...
我刚刚发现一个问题,虽然不完全像你的问题,但对我有用。通过这个问题,你可以找出哪个COM端口来自蓝牙设备: StackOverflow - Determine if serial port is normal COM or 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<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;
}