• 问题解决——获得当前系统已有的串口号


    ==================================声明==================================

    本文原创,转载请显要的注明作者和出处,并保证文章的完整性(包括本声明)。

    本文不定期修改完善,为保证内容正确,建议移步原文处阅读。

    本文链接:http://www.cnblogs.com/wlsandwho/p/4210481.html

    =======================================================================

    最近做的东西要用到串口,初始化界面的时候要列出一个可用的串口列表。

    =======================================================================

    最初我打算枚举设备,感觉好麻烦的样子。

    网上好多都在说,i从1到N,挨个打开关闭一遍……这特么在逗我?

    =======================================================================

    思索了一下(虚词),打算从注册表入手,毕竟所有的(可使用)设备都是要在注册表里注册的。

    定下了方向,就准备资料了。

    =======================================================================

    1 串口在注册表里的位置:HKEY_LOCAL_MACHINEHARDWAREDEVICEMAPSERIALCOMM。

    2 所使用的主要函数:RegEnumValue,这个可以参见MSDN(http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=ZH-CN&k=k%28%22WINREG%2fREGENUMVALUE%22%29;k%28REGENUMVALUE%29;k%28DevLang-%22C%2B%2B%22%29;k%28TargetOS-WINDOWS%29&rd=true),刚好这个函数给出了示例代码(http://msdn.microsoft.com/en-us/library/ms724256%28v=vs.85%29.aspx)。

    =======================================================================

    下面是微软的代码。

    // QueryKey - Enumerates the subkeys of key and its associated values.
    //     hKey - Key whose subkeys and values are to be enumerated.
    
    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    #define MAX_KEY_LENGTH 255
    #define MAX_VALUE_NAME 16383
     
    void QueryKey(HKEY hKey) 
    { 
        TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
        DWORD    cbName;                   // size of name string 
        TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
        DWORD    cchClassName = MAX_PATH;  // size of class string 
        DWORD    cSubKeys=0;               // number of subkeys 
        DWORD    cbMaxSubKey;              // longest subkey size 
        DWORD    cchMaxClass;              // longest class string 
        DWORD    cValues;              // number of values for key 
        DWORD    cchMaxValue;          // longest value name 
        DWORD    cbMaxValueData;       // longest value data 
        DWORD    cbSecurityDescriptor; // size of security descriptor 
        FILETIME ftLastWriteTime;      // last write time 
     
        DWORD i, retCode; 
     
        TCHAR  achValue[MAX_VALUE_NAME]; 
        DWORD cchValue = MAX_VALUE_NAME; 
     
        // Get the class name and the value count. 
        retCode = RegQueryInfoKey(
            hKey,                    // key handle 
            achClass,                // buffer for class name 
            &cchClassName,           // size of class string 
            NULL,                    // reserved 
            &cSubKeys,               // number of subkeys 
            &cbMaxSubKey,            // longest subkey size 
            &cchMaxClass,            // longest class string 
            &cValues,                // number of values for this key 
            &cchMaxValue,            // longest value name 
            &cbMaxValueData,         // longest value data 
            &cbSecurityDescriptor,   // security descriptor 
            &ftLastWriteTime);       // last write time 
     
        // Enumerate the subkeys, until RegEnumKeyEx fails.
        
        if (cSubKeys)
        {
            printf( "
    Number of subkeys: %d
    ", cSubKeys);
    
            for (i=0; i<cSubKeys; i++) 
            { 
                cbName = MAX_KEY_LENGTH;
                retCode = RegEnumKeyEx(hKey, i,
                         achKey, 
                         &cbName, 
                         NULL, 
                         NULL, 
                         NULL, 
                         &ftLastWriteTime); 
                if (retCode == ERROR_SUCCESS) 
                {
                    _tprintf(TEXT("(%d) %s
    "), i+1, achKey);
                }
            }
        } 
     
        // Enumerate the key values. 
    
        if (cValues) 
        {
            printf( "
    Number of values: %d
    ", cValues);
    
            for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) 
            { 
                cchValue = MAX_VALUE_NAME; 
                achValue[0] = ''; 
                retCode = RegEnumValue(hKey, i, 
                    achValue, 
                    &cchValue, 
                    NULL, 
                    NULL,
                    NULL,
                    NULL);
     
                if (retCode == ERROR_SUCCESS ) 
                { 
                    _tprintf(TEXT("(%d) %s
    "), i+1, achValue); 
                } 
            }
        }
    }
    
    void __cdecl _tmain(void)
    {
       HKEY hTestKey;
    
       if( RegOpenKeyEx( HKEY_CURRENT_USER,
            TEXT("SOFTWARE\Microsoft"),
            0,
            KEY_READ,
            &hTestKey) == ERROR_SUCCESS
          )
       {
          QueryKey(hTestKey);
       }
       
       RegCloseKey(hTestKey);
    }

    运行了下,发现这代码是2个功能的,而我现在只需要第2个功能。

    于是稍微改一下代码即可。

     1 void QueryKey(HKEY hKey) 
     2 {               
     3     TCHAR    achClass[MAX_PATH] = TEXT(""); 
     4     DWORD    cchClassName = MAX_PATH; 
     5     DWORD    cSubKeys=0;          
     6     DWORD    cbMaxSubKey;         
     7     DWORD    cchMaxClass;         
     8     DWORD    cValues;             
     9     DWORD    cchMaxValue;         
    10     DWORD    cbMaxValueData;      
    11     DWORD    cbSecurityDescriptor;
    12     FILETIME ftLastWriteTime;     
    13 
    14     DWORD i, retCode; 
    15 
    16     TCHAR  achValue[MAX_VALUE_NAME]; 
    17     DWORD cchValue = MAX_VALUE_NAME; 
    18     BYTE byteData[MAX_VALUE_NAME];
    19     DWORD dwData=MAX_VALUE_NAME;
    20 
    21     retCode = RegQueryInfoKey(
    22                             hKey,                    
    23                             achClass,                
    24                             &cchClassName,           
    25                             NULL,                    
    26                             &cSubKeys,               
    27                             &cbMaxSubKey,            
    28                             &cchMaxClass,            
    29                             &cValues,                
    30                             &cchMaxValue,            
    31                             &cbMaxValueData,         
    32                             &cbSecurityDescriptor,   
    33                             &ftLastWriteTime);       
    34 
    35     if (cValues) 
    36     {
    37         for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) 
    38         { 
    39             cchValue = MAX_VALUE_NAME; 
    40             achValue[0] = ''; 
    41             dwData=MAX_VALUE_NAME;
    42             byteData[0] = '';
    43 
    44             retCode = RegEnumValue(hKey, i, 
    45                 achValue, 
    46                 &cchValue, 
    47                 NULL, 
    48                 NULL,
    49                 byteData,
    50                 &dwData);
    51 
    52             if (retCode == ERROR_SUCCESS ) 
    53             {     
    54                 CString strCOM= (wchar_t*)byteData;
    55             } 
    56         }
    57     }
    58 }

    第54行,我取得了想要的结果。

    =======================================================================

    为了以后方便使用,可以将其封装到类中,比方说CEnumSerialPortWLS。

    我的CEnumSerialPortWLS中有一个set,这样,把

    1  CString strCOM= (wchar_t*)byteData;

    后面加上insert就行了。

    ===============================记吃不记打==================================

    有一个值得注意的地方就是,RegEnumValue函数返回的byteData,是UNICODE的,所以可以直接强制转换使用。

    这个地方我犯了一个错误,我从来都是使用TCHAR之类的宏,不使用wchar_t这些东西,所以对于得到的错误结果困惑了好一阵子,

    以后要记住:

    已明确的强制类型转换要使用明确的类型。

    ================================耻辱墙===================================

    http://www.cnblogs.com/wlsandwho/p/4206472.html

    算了还是贴代码吧。

     1 #include <windows.h>
     2 #include <vector>
     3 #include <string>
     4 
     5 std::vector<std::wstring> GetAllSerialPorts()
     6 {
     7     const int MAX_KEY_LENGTH=255;
     8     const int MAX_VALUE_NAME = 16383;
     9 
    10     std::vector<std::wstring> vctTemp;
    11 
    12     HKEY hTestKey;
    13 
    14     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\DEVICEMAP\SERIALCOMM"), 0, KEY_READ, &hTestKey) != ERROR_SUCCESS)
    15     {
    16         return vctTemp;
    17     }
    18 
    19     TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
    20     DWORD    cchClassName = MAX_PATH;  // size of class string 
    21     DWORD    cSubKeys = 0;               // number of subkeys 
    22     DWORD    cbMaxSubKey;              // longest subkey size 
    23     DWORD    cchMaxClass;              // longest class string 
    24     DWORD    cValues;              // number of values for key 
    25     DWORD    cchMaxValue;          // longest value name 
    26     DWORD    cbMaxValueData;       // longest value data 
    27     DWORD    cbSecurityDescriptor; // size of security descriptor 
    28     FILETIME ftLastWriteTime;      // last write time 
    29 
    30     DWORD i, retCode;
    31 
    32     TCHAR  achValue[MAX_VALUE_NAME];
    33     DWORD cchValue = MAX_VALUE_NAME;
    34     BYTE byteData[MAX_VALUE_NAME];
    35     DWORD dwData = MAX_VALUE_NAME;
    36 
    37     retCode = RegQueryInfoKey(
    38         hTestKey,
    39         achClass,
    40         &cchClassName,
    41         NULL,
    42         &cSubKeys,
    43         &cbMaxSubKey,
    44         &cchMaxClass,
    45         &cValues,
    46         &cchMaxValue,
    47         &cbMaxValueData,
    48         &cbSecurityDescriptor,
    49         &ftLastWriteTime);
    50 
    51     if (cValues)
    52     {
    53         for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
    54         {
    55             cchValue = MAX_VALUE_NAME;
    56             achValue[0] = '';
    57             dwData = MAX_VALUE_NAME;
    58             byteData[0] = '';
    59 
    60             retCode = RegEnumValue(hTestKey, i,
    61                 achValue,
    62                 &cchValue,
    63                 NULL,
    64                 NULL,
    65                 byteData,
    66                 &dwData);
    67 
    68             if (retCode == ERROR_SUCCESS)
    69             {
    70                 std::wstring strCOM = (wchar_t*)byteData;
    71                 vctTemp.push_back(strCOM);
    72             }
    73         }
    74     }
    75 
    76     RegCloseKey(hTestKey);
    77 
    78     return vctTemp;
    79 }
    80 
    81 int main()
    82 {
    83     auto a = GetAllSerialPorts();
    84     return 0;
    85 }
  • 相关阅读:
    Node.js 基于 ursa 模块的 RSA 加密解密(已与IOS,Android实现加密通信)
    Mac安装SecureCRT
    lodash underscore 对象数组排序 sortBy 小记
    Spring5--@Indexed注解加快启动速度
    spring的元注解
    RxJava原理学习
    RabbitMQ知识点一
    消息中间件知识点
    Android打开doc、xlsx、ppt等office文档解决方案
    IT观察】网络通信、图片显示、数据库操作……Android程序员如何利用开源框架
  • 原文地址:https://www.cnblogs.com/wlsandwho/p/4210481.html
Copyright © 2020-2023  润新知