7
votes

Identifier le port COM avec Vid et PID pour un périphérique USB attaché à x64

Comme suivant, je suis capable d'obtenir des noms de port COM USB attachés à la machine Win7OS 32bit, par CoD et Vid, mais lors de l'exécution de X64, il est bloqué dans la ligne suivante:

static List<string> ComPortNames(String VID, String PID)
    {
        String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
        Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
        List<string> comports = new List<string>();

        RegistryKey rk1 = Registry.LocalMachine;
        RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");

        foreach (String s3 in rk2.GetSubKeyNames())
        {

            RegistryKey rk3 = rk2.OpenSubKey(s3);
            foreach (String s in rk3.GetSubKeyNames())
            {
                if (_rx.Match(s).Success)
                {
                    RegistryKey rk4 = rk3.OpenSubKey(s);
                    foreach (String s2 in rk4.GetSubKeyNames())
                    {
                        RegistryKey rk5 = rk4.OpenSubKey(s2);
                        RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                        comports.Add((string)rk6.GetValue("PortName"));
                    }
                }
            }
        }
        return comports;
    }


4 commentaires

Cela n'est pas laissable, au moins une trace de pile est requise.


Cette méthode renvoie la liste des ports COM qui attachent notre périphérique ex: COM3, COM4, ​​etc., problème est que cela ne fonctionne pas sur x64


Comme il pourrait être pertinent pour les autres qui viennent ici: la simple raison est probablement due à rk6 étant null car "Paramètres de périphérique" clé ne fait pas existent sur chaque nœud de périphérique et, en tant que tel, il n'est pas liée à une version 32 bits ou 64 bits du système d'exploitation


@Duayalakmal, la réponse de Youkko a-t-elle résolu votre problème? Si oui, pouvez-vous l'accepter?


5 Réponses :


2
votes

2 commentaires

Pour ajouter à cela, essayez de télécharger le Créateur de code WMI Creator Microsoft.com /en-us/download/confirmation.aspx?id=8572 . Définissez l'espace de noms sur "root \ wmi" et les classes sur "msserial_portname", vous devriez être en mesure de modifier le chercheur de gestionObjectearer pour interroger que "InstanceCename" (les informations USB d'un port COM) contiennent une chaîne particulière (par exemple " Pid_7523 "). Si je reçois un exemple de travail, je vais le mettre comme une réponse ici plus tard.


Il semble y avoir divers problèmes de cette méthode (par exemple, Windows ne mett toujours pas toujours le numéro de port COM dans la description, l'accès se refuse des erreurs lors de l'utilisation de racines \ WMI / Puréight Aucun port COM affiché sur Win10). La méthode de Peterj semble le meilleur Sofar.



7
votes

En lisant votre code, j'ai découvert que le chemin actuel que vous consultez dans le registre ne contient aucune information sur les ports. Mais j'ai trouvé un moyen de le lire en faisant ce petit changement:

    static List<string> ComPortNames(String VID, String PID)
    {
        String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
        Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
        List<string> comports = new List<string>();

        RegistryKey rk1 = Registry.LocalMachine;
        RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");

        foreach (String s3 in rk2.GetSubKeyNames())
        {

            RegistryKey rk3 = rk2.OpenSubKey(s3);
            foreach (String s in rk3.GetSubKeyNames())
            {
                if (_rx.Match(s).Success)
                {
                    RegistryKey rk4 = rk3.OpenSubKey(s);
                    foreach (String s2 in rk4.GetSubKeyNames())
                    {
                        RegistryKey rk5 = rk4.OpenSubKey(s2);
                        string location = (string)rk5.GetValue("LocationInformation");
                        if (!String.IsNullOrEmpty(location))
                        {
                            string port = location.Substring(location.IndexOf('#') + 1, 4).TrimStart('0');
                            if (!String.IsNullOrEmpty(port)) comports.Add(String.Format("COM{0:####}", port));
                        }
                        //RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                        //comports.Add((string)rk6.GetValue("PortName"));
                    }
                }
            }
        }
        return comports;
    }


2 commentaires

Aussi, utilisez "si (! String.isnullorempty (emplacement))" au lieu de "si (emplacement! = String.empty)" ... J'ai trouvé que l'emplacement peut être null.


EmplacementInformation est l'emplacement matériel du périphérique USB, pas com



9
votes

Pendant que je testais la réponse de Youkko sous Windows 10 x64 J'avais des résultats étranges et je regarde le registre sur ma machine, le emplacementInformation "/ code> clés contenait des chaînes telles que port_ # 0002.hub_ # 0003 code> afin qu'ils soient liés au hub / port USB, le périphérique est connecté au port COM. attribué par Windows.

Donc, dans mon cas, je devais être COM2 inclus qui est un port matériel sur ma carte mère et je suis ignoré le port de COM5, je m'attendais, mais c'était situé sous la clé de registre code>. Je ne sais pas si quelque chose a changé depuis la version de Windows que vous utilisiez, mais je pense que votre problème principal n'aurait peut-être pas de vérifier les valeurs nulles sur les touches. P>

La version légèrement modifiée suivante semble fonctionner Fine sur une variété ou des systèmes Windows 7/10 et X32 / 64 et j'ai également ajouté une vérification de Serialport.geportNames () code> Pour vous assurer que le périphérique est disponible et branché sur le système avant de revenir. IT: P>

static List<string> ComPortNames(String VID, String PID)
{
    String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
    Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
    List<string> comports = new List<string>();

    RegistryKey rk1 = Registry.LocalMachine;
    RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");

    foreach (String s3 in rk2.GetSubKeyNames())
    {
        RegistryKey rk3 = rk2.OpenSubKey(s3);
        foreach (String s in rk3.GetSubKeyNames())
        {
            if (_rx.Match(s).Success)
            {
                RegistryKey rk4 = rk3.OpenSubKey(s);
                foreach (String s2 in rk4.GetSubKeyNames())
                {
                    RegistryKey rk5 = rk4.OpenSubKey(s2);
                    string location = (string)rk5.GetValue("LocationInformation");
                    RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                    string portName = (string)rk6.GetValue("PortName");
                    if (!String.IsNullOrEmpty(portName) && SerialPort.GetPortNames().Contains(portName))
                        comports.Add((string)rk6.GetValue("PortName"));
                }
            }
        }
    }
    return comports;
}


1 commentaires

Au moment où j'ai répondu, même Windows 8 n'existait pas. Ma réponse fonctionne sous Windows 7. Mais merci beaucoup pour cette contribution. Chaque réponse nécessite des mises à jour parfois :-)



4
votes

Voici ma prise sur ceci (même si ce n'est pas un direct A au Q)

  • Les périphériques USB sont toujours (et ont toujours) énumérés sous HKLM \ System \ CurrentControlset \ Enum \ USB code> (NOTE USB code> à la fin) LI>
    • Les nœuds de périphérique ont le format vid_xxxx & pid_xxxx * code> où xxxx code> est hexadécimal, il peut y avoir des données de fonction supplémentaires à la fin li> ul> li>
      • Chaque nœud de périphérique dispose d'un nœud de sous-identifiant basé sur la série de série ou d'autres données du périphérique et des fonctions li> ul> li>
        • nœud identifiant peut avoir une valeur "symboleName" code> quels moments ont parfois le com en paranthèses telle que "Port série virtuel (COM6)" LI> ul> li>
          • Chemier résultant: HKLM \ System \ CurrentControlset \ Enum \ USB \ Vid_XXXXX & PID_XXXX * \ * \ Paramètres de périphérique \ code> a une valeur nommée "PortName" Li> ul> li>
          • Les ports COM actuellement disponibles sont répertoriés par System.IO.PORTS.SERIALPORT.GETPORTS () CODE> LI>
          • opensubkey code> Implements Idisposable CODE> et doit avoir à l'aide de code> ou .Dispose () code> sur eux p>

            using System.IO.Ports;
            using System.Linq;
            using Microsoft.Win32;
            
            public class UsbSerialPort
            {
                public readonly string PortName;
                public readonly string DeviceId;
                public readonly string FriendlyName;
            
                private UsbSerialPort(string name, string id, string friendly)
                {
                    PortName = name;
                    DeviceId = id;
                    FriendlyName = friendly;
                }
            
                private static IEnumerable<RegistryKey> GetSubKeys(RegistryKey key)
                {
                    foreach (string keyName in key.GetSubKeyNames())
                        using (var subKey = key.OpenSubKey(keyName))
                            yield return subKey;
                }
            
                private static string GetName(RegistryKey key)
                {
                    string name = key.Name;
                    int idx;
                    return (idx = name.LastIndexOf('\\')) == -1 ?
                        name : name.Substring(idx + 1);
                }
            
                public static IEnumerable<UsbSerialPort> GetPorts()
                {
                    var existingPorts = SerialPort.GetPortNames();
                    using (var enumUsbKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\USB"))
                    {
                        if (enumUsbKey == null)
                            throw new ArgumentNullException("USB", "No enumerable USB devices found in registry");
                        foreach (var devBaseKey in GetSubKeys(enumUsbKey))
                        {
                            foreach (var devFnKey in GetSubKeys(devBaseKey))
                            {
                                string friendlyName =
                                    (string) devFnKey.GetValue("FriendlyName") ??
                                    (string) devFnKey.GetValue("DeviceDesc");
                                using (var devParamsKey = devFnKey.OpenSubKey("Device Parameters"))
                                {
                                    string portName = (string) devParamsKey?.GetValue("PortName");
                                    if (!string.IsNullOrEmpty(portName) &&
                                        existingPorts.Contains(portName))
                                        yield return new UsbSerialPort(portName, GetName(devBaseKey) + @"\" + GetName(devFnKey), friendlyName);
                                }
                            }
            
                        }
                    }
                }
            
                public override string ToString()
                {
                    return string.Format("{0} Friendly: {1} DeviceId: {2}", PortName, FriendlyName, DeviceId);
                }
            }
            


0 commentaires

2
votes

OK, à l'aide de GestionObjecteReather (il donne à COM-Port Index et Vid et PID s'ils existent):

        List < List <string>> USBCOMlist = new List<List<string>>();
        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_PnPEntity");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                if (queryObj["Caption"].ToString().Contains("(COM"))
                {
                    List<string> DevInfo = new List<string>();

                    string Caption = queryObj["Caption"].ToString();
                    int CaptionIndex = Caption.IndexOf("(COM");
                    string CaptionInfo = Caption.Substring(CaptionIndex + 1).TrimEnd(')'); // make the trimming more correct                 

                    DevInfo.Add(CaptionInfo);

                    string deviceId = queryObj["deviceid"].ToString(); //"DeviceID"

                    int vidIndex = deviceId.IndexOf("VID_");
                    int pidIndex = deviceId.IndexOf("PID_");
                    string vid = "", pid = "";

                    if (vidIndex != -1 && pidIndex != -1)
                    {
                        string startingAtVid = deviceId.Substring(vidIndex + 4); // + 4 to remove "VID_"                    
                        vid = startingAtVid.Substring(0, 4); // vid is four characters long
                                                             //Console.WriteLine("VID: " + vid);
                        string startingAtPid = deviceId.Substring(pidIndex + 4); // + 4 to remove "PID_"                    
                        pid = startingAtPid.Substring(0, 4); // pid is four characters long
                    }

                    DevInfo.Add(vid);
                    DevInfo.Add(pid);

                    USBCOMlist.Add(DevInfo);
                }

            }
        }
        catch (ManagementException e)
        {
            MessageBox.Show(e.Message);
        }


0 commentaires