2008-11-20 26 views
12

Tôi có modem GSM được kết nối qua USB. Modem tạo 2 cổng nối tiếp. Đầu tiên được tự động gắn vào modem, chương trình thứ hai trong Device Manager là "HUAWEI Mobile Connect - Giao diện người dùng 3G PC (COM6)"Làm cách nào để có được tên thân thiện của cổng COM trong Windows?

Cổng thứ hai được sử dụng để nhận thông tin quan trọng từ modem, chẳng hạn như chất lượng tín hiệu ; gửi và nhận tin nhắn văn bản; và một loạt các chức năng khác.

Tôi đang viết một ứng dụng sẽ bao bọc một số tính năng được cung cấp bởi cổng thứ hai. Những gì tôi cần là một phương pháp lửa chắc chắn để xác định cổng COM là phụ tùng. Lặp lại các cổng và kiểm tra phản hồi tới "ATE0" là không đủ. Cổng của modem thường là số thấp hơn, và khi kết nối quay số không hoạt động, nó sẽ trả lời "ATE0" giống như cổng thứ hai.

Những gì tôi đã nghĩ đến làm là lặp lại các cổng và kiểm tra tên thân thiện của chúng, như nó hiển thị trong Trình quản lý thiết bị. Bằng cách đó tôi có thể liên kết cổng trong ứng dụng của tôi với cổng có nhãn "HUAWEI Mobile Connect - Giao diện người dùng giao diện người dùng 3G (COM6)" trong Trình quản lý thiết bị. Tôi chưa tìm thấy bất kỳ thông tin nào cho phép tôi lấy tên đó theo lập trình.

Trả lời

7

Một thời gian dài trước đây tôi đã viết một tiện ích cho một khách hàng để làm điều này, nhưng đối với một GPS chứ không phải là một modem.

Tôi vừa nhìn nó, và bit mà nhảy-bán như vậy là có thể hữu ích là:

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)) 
    { 
... 

(Bạn gọi bit này trong một vòng lặp với incrementing nDevice)

và sau đó

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

tìm tên thiết bị.

Hy vọng rằng điều đó sẽ giúp bạn đi đúng hướng.

+0

Điều này có vẻ như nó chỉ có thể thực hiện thủ thuật. Tôi đang viết một bài kiểm tra ngay bây giờ. Cảm ơn một triệu :) – RichieACC

2

Thông tin được đăng bởi Will Dean hữu ích nhất. Đây là mã mà cuối cùng đã làm việc cho tôi. Tất cả mọi thứ trong lớp PInvoke được lấy nguyên văn từ http://www.pinvoke.net. Tôi đã phải thay đổi một loại dữ liệu ở đây hoặc ở đó để làm cho nó hoạt động (như khi sử dụng một enum thay vì một uint) nhưng nó phải dễ dàng tìm ra.

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; 
} 

Tôi nghĩ rằng dòng Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM")); là một chút vụng về, đề xuất về cách làm sạch nó sẽ được đánh giá cao.

Cảm ơn sự giúp đỡ của bạn về vấn đề này Will, không có bạn, tôi vẫn đang tìm kiếm trên google.

1

Rất vui khi nó hoạt động.

Bạn có thể thử:

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

cho phù hợp với chuỗi của bạn..

Là điểm phong cách .NET, tôi sẽ thêm "using System.Text" và tôi sẽ không bắt đầu tên biến cục bộ với thủ đô và nếu tôi cảm thấy thực sự đạo đức, tôi có thể đặt SetupDiDestroyDeviceInfoList trong mệnh đề cuối cùng {}.

+0

Regex trông thanh lịch hơn. Một điều tôi đã phải thay đổi mặc dù: "COM \ s? \ D +" Sẽ không phải lúc nào cũng có khoảng trắng giữa COM và số, vì vậy nó cần phải phù hợp với 0 hoặc nhiều hơn. Cảm ơn bạn lần nữa. – RichieACC

3

Sau khi bạn xác định một thiết bị Serial Port là một trong những bạn muốn (bằng cách nhìn vào Tên thân thiện của nó, bằng cách kiểm tra thiết bị mẹ vv), cách thích hợp để có được tên của cổng có lẽ sẽ là:

  • gọi SetupDiOpenDevRegKey(hDevInfo, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) để có được những HKEY đến thiết bị cái gọi là chìa khóa
  • truy vấn này khóa registry cho giá trị REG_SZ "PortName"
  • đừng quên để đóng HKEY :)

Tuy nhiên, điều này có thể yêu cầu rất nhiều interop trong C# nó thậm chí không buồn cười, vì vậy tôi không đổ lỗi cho bạn nếu bạn giữ cho các giải pháp phân tích cú pháp chuỗi.

0

Sử dụng phương pháp được đăng bởi LiGenChen. Phương thức ComPortSetupAPISetupDiClassGuids đưa ra thời gian và tên thân thiện nhất.

+0

Sẽ hữu ích nếu bạn sửa đổi câu trả lời của mình với thông tin liên quan hơn từ liên kết – Hambone

1

Phiên bản C++ dựa trên câu trả lời @Will Dean.

#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 
     } 
    } 
} 
Các vấn đề liên quan