Como posso encontrar um número de porta COM de um dispositivo bluetooth em C#?

A minha empresa desenvolveu um dispositivo que comunica com um PC via Bluetooth usando uma porta de comunicação virtual.

agora precisamos de um usuário para emparelhar um dispositivo com um PC (MS Windows OS) primeiro e, em seguida, digitar o seu número de porta com manualmente em nossa aplicação(eu aposto 95% dos usuários vai falhar nesta taks).

Por isso, gostaria que a minha aplicação apresentasse a um utilizador uma lista de dispositivos bluetooth emparelhados (uma lista dos seus "nomes amigáveis") e, depois disso, gostaria de descobrir a COM do dispositivo selected número da porta automaticamente.

Como posso fazê-lo em c#? (uma solução independente da pilha bluetooth instalada é apreciada).

Obrigado antecipadamente.

Author: Łukasz Bownik, 2010-01-18

6 answers

Veja a minha resposta em Widcomm bluetooth : como abrir a COM virtual para a minha compreensão da licença: usar a versão binária é livre para uso comercial. E também que sou responsável pela biblioteca.

Uma pequena digressão. Não sou grande fã de comunicações virtuais. Parece sempre muito mais fácil usar uma conexão direta 'sockets', em vez de tentar configurar uma porta COM, e tentar encontrar o nome que foi criado como (Veja abaixo!), e depois tem de abra um SerialPort para usá-lo, e então, se a conexão for perdida, não se sabe e tem simplesmente de continuar a refazer... Com a Biblioteca é muito mais fácil de apenas criar e usar essa conexão Bluetooth direta!
No entanto, pode querer uma solução para a sua tarefa actual neste momento. :- ) Então, use WMI para encontrar as portas de comunicação atuais no lugar e ver se alguma delas são para o seu dispositivo. Por exemplo em 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

Naquele grande fio comprido se vê o endereço do dispositivo alvo: 00803A686519. Pode-se usar o WMI do.NET, executar essa consulta, filtrar os com "BTHENUM", e então analisar o endereço.

Se precisar de criar uma nova porta de COM virtual Bluetooth, use 32feet.NET ' s BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort) API. Ver a secção "portas seriais Bluetooth" no Guia Do Utilizador, por exemplo em http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html, e a documentação da classe na lancar.

Infelizmente, a API Win32 nativa a que chamamos não diz o nome do Porto COM que ele criou! :- (Então execute a consulta WMI antes e depois da chamada para ver qual novo nome apareceu (ou use System.IO.Ports.SerialPort.GetPortNames como seu mais simples). Isso é tudo específico para a pilha de Bluetooth da Microsoft. Eu não investiguei como outros stacks se comportam a este respeito. Após uma breve verificação, as portas seriais de Widcomm aparecem em SerialPort.GetPortNames but not in the WMI query...
 8
Author: alanjmcf, 2017-05-23 11:46:52

Primeiro, crie um pesquisador de objectos de gestão para procurar na base de dados WMI:

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

A seguir, use o LINQ para obter todas as portas seriais numa consulta:

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

Agora pode imprimir todas as portas de comunicação, os seus nomes amigáveis e pode até filtrar através dos PNPDeviceID para encontrar o endereço do dispositivo bluetooth. Aqui está um exemplo:

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);
        }
    }
}
 4
Author: Matt Williams, 2015-11-10 14:54:15
Consegui obter o nome bluetooth e a porta de comunicações, mexendo na chave do registo

O pseudo-código para obter a informação bluetooth está em baixo:

  • enumerar todas as comunicações disponíveis no PNP
  • obter o dispositivo classGuid
  • procura o endereço bluetooth na classGuid
  • quando o endereço bluetooth é conhecido, o nome bluetooth pode ser obtido a partir deste registo SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices
O código está em baixo. GetBluetoothPort (), ele irá devolver uma lista de dispositivos bluetooth, e você poderia conectá-los passando o número da porta COM para a classe SerialPort
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;
}
 2
Author: Tim, 2016-03-30 01:49:52
Talvez não seja o que procura, e talvez já tenha encontrado a sua resposta... Acabei de encontrar uma pergunta que não é exactamente como a tua, mas que trabalhava para mim.. Com este você pode descobrir qual de suas portas de comunicação são de um dispositivo Bluetooth: StackOverflow-determinar se a porta série é normal COM ou SPP. Espero que ajude de alguma forma. Se descobrires como fazer o que querias, por favor avisa-me. Obrigado.
 1
Author: Vic, 2017-05-23 12:34:08
Então, para obter a informação sobre um dispositivo remoto, incluindo o seu nome, usando 32feet.NET do:
BluetoothAddress addr = ... ...
BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr);
string name = info.DeviceName;

Se não estiver a usar a biblioteca, terá de invocar o BluetoothGetDeviceInfo do Win32.

 0
Author: alanjmcf, 2010-01-22 17:15:51
    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;
    }
 0
Author: CJ_, 2017-04-25 20:22:44