2008-11-20 6 views
12

J'ai un modem GSM connecté via USB. Le modem crée 2 ports série. Le premier est automatiquement connecté au modem, le deuxième s'affiche dans le Gestionnaire de périphériques sous la forme "HUAWEI Mobile Connect - Interface PC UI 3G (COM6)"Comment puis-je obtenir le nom convivial d'un port COM dans Windows?

Le deuxième port est utilisé pour obtenir des informations vitales du modem, telles que la qualité du signal ; envoyer et recevoir des messages texte; et une foule d'autres fonctions.

Je suis en train d'écrire une application qui résumera certaines des fonctionnalités fournies par le second port. Ce dont j'ai besoin, c'est d'une méthode sûre pour identifier le port COM qui est celui de rechange. Itérer les ports et vérifier une réponse à "ATE0" n'est pas suffisant. Le port du modem est généralement le numéro le plus bas, et lorsqu'une connexion commutée n'est pas active, il répond à "ATE0" de la même manière que le second port. Ce que je pensais faire est d'itérer les ports et de vérifier leur nom convivial, comme il le montre dans le Gestionnaire de périphériques. De cette façon, je peux relier le port de mon application au port "HUAWEI Mobile Connect - Interface PC UI 3G (COM6)" dans le Gestionnaire de périphériques. Je n'ai pas encore trouvé d'informations qui me permettront d'obtenir ce nom par programme.

Répondre

7

Il ya longtemps, j'ai écrit un utilitaire pour un client pour faire cela, mais pour un GPS plutôt qu'un modem.

Je viens de regardé, et les bits qui sautent-out comme étant peut-être utiles sont:

GUID guid = GUID_DEVCLASS_PORTS; 

SP_DEVICE_INTERFACE_DATA interfaceData; 
ZeroMemory(&interfaceData, sizeof(interfaceData)); 
interfaceData.cbSize = sizeof(interfaceData); 

SP_DEVINFO_DATA devInfoData; 
ZeroMemory(&devInfoData, sizeof(devInfoData)); 
devInfoData.cbSize = sizeof(devInfoData); 

if(SetupDiEnumDeviceInfo(
    hDeviceInfo,   // Our device tree 
    nDevice,   // The member to look for 
    &devInfoData 
    )) 
{ 
    DWORD regDataType; 

    BYTE hardwareId[300]; 
    if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, &regDataType, hardwareId, sizeof(hardwareId), NULL)) 
    { 
... 

(Vous appelez ce bit dans une boucle avec incrémenter nDevice)

puis

BYTE friendlyName[300]; 
     if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL)) 
     { 
      strFriendlyNames += (LPCTSTR)friendlyName; 
      strFriendlyNames += '\n'; 
     } 

qui trouve le nom du périphérique.

J'espère que cela vous aidera dans la bonne direction.

+0

On dirait que ça pourrait faire l'affaire. J'écris un test maintenant. Merci un million :) – RichieACC

2

Les informations affichées par Will Dean ont été des plus utiles. C'est le code qui a finalement fonctionné pour moi. Tout dans la classe PInvoke a été pris textuellement de http://www.pinvoke.net. J'ai dû changer un type de données ici ou là pour le faire fonctionner (comme lorsque vous utilisez une énumération au lieu d'un uint), mais il devrait être facile à comprendre.

internal static string GetComPortByDescription(string Description) 
{ 
    string Result = string.Empty; 
    Guid guid = PInvoke.GUID_DEVCLASS_PORTS; 
    uint nDevice = 0; 
    uint nBytes = 300; 
    byte[] retval = new byte[nBytes]; 
    uint RequiredSize = 0; 
    uint PropertyRegDataType = 0; 

    PInvoke.SP_DEVINFO_DATA devInfoData = new PInvoke.SP_DEVINFO_DATA(); 
    devInfoData.cbSize = Marshal.SizeOf(typeof(PInvoke.SP_DEVINFO_DATA)); 

    IntPtr hDeviceInfo = PInvoke.SetupDiGetClassDevs(
     ref guid, 
     null, 
     IntPtr.Zero, 
     PInvoke.DIGCF.DIGCF_PRESENT); 

    while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData)) 
    { 
     if (PInvoke.SetupDiGetDeviceRegistryProperty(
       hDeviceInfo, 
       ref devInfoData, 
       PInvoke.SPDRP.SPDRP_FRIENDLYNAME, 
       out PropertyRegDataType, 
       retval, 
       nBytes, 
       out RequiredSize)) 
     { 
      if (System.Text.Encoding.Unicode.GetString(retval).Substring(0, Description.Length).ToLower() == 
       Description.ToLower()) 
      { 
       string tmpstring = System.Text.Encoding.Unicode.GetString(retval); 
       Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM")); 
      } // if retval == description 
     } // if (PInvoke.SetupDiGetDeviceRegistryProperty(... SPDRP_FRIENDLYNAME ... 
    } // while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData)) 

    PInvoke.SetupDiDestroyDeviceInfoList(hDeviceInfo); 
    return Result; 
} 

Je pense que la ligne Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM")); est un peu maladroite, des suggestions sur la façon de nettoyer seraient appréciés.

Merci pour votre aide à ce sujet Will, sans vous, je serais encore à la recherche de google.

1

Heureux que cela a fonctionné.

Vous pouvez essayer:

Regex.Match (tmpstring, @ "COM \ s \ d +") ToString()

pour votre chaîne correspondant.. En tant que points de style .NET, j'ajouterais un "using System.Text", et je ne lancerais pas de noms de variables locales avec des majuscules, et si je me sentais vraiment vertueux, je mettrais probablement le SetupDiDestroyDeviceInfoList dans un enfin {} clause.

+0

L'expression rationnelle semble plus élégante. Une chose que j'ai dû changer cependant: "COM \ s? \ D +" Il n'y aura pas toujours d'espace entre COM et le nombre, donc il doit correspondre à 0 ou plus. Merci encore. – RichieACC

3

Après avoir déterminé un dispositif de port série est celui que vous voulez (en regardant ses amis Nom, en vérifiant son dispositif parent, etc.), la bonne façon d'obtenir le nom du port serait probablement:

  • invoquer SetupDiOpenDevRegKey(hDevInfo, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) pour obtenir le HKEY à la soi-disant dispositif clé
  • requête cette clé de registre pour la valeur REG_SZ « PortName »
  • ne pas oublier de fermer le HKEY :)

Cependant, cela peut nécessiter beaucoup d'interopérabilité en C# ce n'est même pas drôle, donc je ne vous blâme pas si vous gardez la solution d'analyse de chaîne.

0

Utilisé la méthode publiée par LiGenChen. La méthode ComPortSetupAPISetupDiClassGuids a donné le meilleur temps et le nom convivial.

+0

Il serait utile que vous modifiez votre réponse avec des informations plus pertinentes à partir du lien – Hambone

1

La version C++ basée sur @Will Dean answer.

#include <windows.h> 
#include <initguid.h> 
#include <devguid.h> 
#include <setupapi.h> 

void enumerateSerialPortsFriendlyNames() 
{ 
    SP_DEVINFO_DATA devInfoData = {}; 
    devInfoData.cbSize = sizeof(devInfoData); 

    // get the tree containing the info for the ports 
    HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 
               0, 
               nullptr, 
               DIGCF_PRESENT 
               ); 
    if (hDeviceInfo == INVALID_HANDLE_VALUE) 
    { 
     return; 
    } 

    // iterate over all the devices in the tree 
    int nDevice = 0; 
    while (SetupDiEnumDeviceInfo(hDeviceInfo,   // Our device tree 
           nDevice++,   // The member to look for 
           &devInfoData)) 
    { 
     DWORD regDataType; 
     DWORD reqSize = 0; 

     // find the size required to hold the device info 
     SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize); 
     BYTE hardwareId[reqSize > 1 ? reqSize : 1]; 
     // now store it in a buffer 
     if (SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, &regDataType, hardwareId, sizeof(hardwareId), nullptr)) 
     { 
      // find the size required to hold the friendly name 
      reqSize = 0; 
      SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize); 
      BYTE friendlyName[reqSize > 1 ? reqSize : 1]; 
      // now store it in a buffer 
      if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, friendlyName, sizeof(friendlyName), nullptr)) 
      { 
       // device does not have this property set 
       memset(friendlyName, 0, reqSize > 1 ? reqSize : 1); 
      } 
      // use friendlyName here 
     } 
    } 
} 
Questions connexes