web-dev-qa-db-ja.com

C#でBluetoothデバイスのCOMポート番号を確認するにはどうすればよいですか?

私の会社は、仮想COMポートを使用してBluetooth経由でPCと通信するデバイスを開発しました。

ここで、ユーザーが最初にデバイスをPC(MS Windows OS)とペアリングしてから、そのcomポート番号をアプリケーションに手動で入力する必要があります(ユーザーの95%がこのタスクで失敗するに違いありません)。

そのため、アプリケーションでペアリングされたBluetoothデバイスのリスト(「フレンドリ名」のリスト)をユーザーに提示し、その後、選択したデバイスのCOMポート番号を自動的に確認したいと思います。

どうすればC#でそれを行うことができますか? (インストールされているBluetoothスタックに依存しないソリューションを歓迎します)。

前もって感謝します。

16
Łukasz Bownik

ライセンスの理解については、 Widcomm bluetooth:仮想COMを開く方法 の私の回答を参照してください。バイナリバージョンの使用は商用利用は無料です。そして、私が図書館のメンテナーであることも。

だから、短い余談。私は仮想COMポートの大ファンではありません。 COMポートを設定し、作成された名前を見つけて(以下を参照)、シリアルポートを開いて使用するよりも、直接「ソケット」接続を使用する方が常にはるかに簡単なようです。そして、接続が失われた場合、人は知らず、単に再試行し続ける必要があります...ライブラリを使用すると、その直接Bluetooth接続を作成して使用するだけで非常に簡単になります!

ただし、現時点で現在のタスクの解決策が必要な場合があります。 :-)したがって、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」でクエリをフィルタリングしてから、アドレスを解析できます。

新しいBluetooth仮想COMポートを作成する必要がある場合は、32feet.NETのBluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort)APIを使用してください。ユーザーガイドの「Bluetoothシリアルポート」セクションを参照してください。 http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html 、およびリリースのクラスドキュメント。

残念ながら、私たちが呼び出すネイティブWin32 APIは、それが作成したCOMポートの名前を教えてくれません! :-(したがって、呼び出しの前後にWMIクエリを実行して、どの新しい名前が表示されたかを確認します(または、より単純なものとしてSystem.IO.Ports.SerialPort.GetPortNamesを使用します)。

これはすべて、MicrosoftBluetoothスタックに固有のものです。この点で他のスタックがどのように動作するかについては調査していません。簡単なチェックの後、WidcommのシリアルポートはSerialPort.GetPortNamesに表示されますが、WMIクエリには表示されません...

9
alanjmcf

まず、管理オブジェクトサーチャーを作成して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をフィルタリングしてBluetoothデバイスアドレスを見つけることもできます。次に例を示します。

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
Matt Williams

レジストリキーをいじることでBluetooth名とCOMポートを取得できます

Bluetooth情報を取得するための擬似コードは次のとおりです。

  • pNPで使用可能なすべてのCOMポートを列挙します
  • デバイスclassGuidを取得します
  • classGuidからBluetoothアドレスを検索します
  • bluetoothアドレスがわかっている場合、Bluetooth名はこのレジストリから取得できますSYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices

以下のコードは、GetBluetoothPort()を呼び出すだけで、Bluetoothデバイスのリストが返され、COMポート番号を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
Tim

多分それはあなたが探しているものではなく、多分あなたはすでにあなたの答えを見つけました...

私はちょうどあなたとまったく同じではない質問を見つけましたが、私のために働きました..これであなたはあなたのCOMポートのどれがBluetoothデバイスからのものであるかを見つけることができます: StackOverflow-シリアルポートが通常のCOMまたはSPPであるかどうかを決定します

なんとなくお役に立てば幸いです。あなたがやりたいことをする方法を見つけたら、私に知らせてください。ありがとう。

1
Vic

したがって、32feet.NETを使用して、名前を含むリモートデバイスに関する情報を取得するには、次のようにします。

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

ライブラリを使用しない場合は、Win32のBluetoothGetDeviceInfoをP/Invokeする必要があります。

0
alanjmcf
    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
CJ_