首页 > 代码库 > 问题解决——获得当前系统已有的串口号

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1 串口在注册表里的位置:HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM。

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( "\nNumber of subkeys: %d\n", 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\n"), i+1, achKey);            }        }    }      // Enumerate the key values.     if (cValues)     {        printf( "\nNumber of values: %d\n", cValues);        for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)         {             cchValue = MAX_VALUE_NAME;             achValue[0] = \0;             retCode = RegEnumValue(hKey, i,                 achValue,                 &cchValue,                 NULL,                 NULL,                NULL,                NULL);             if (retCode == ERROR_SUCCESS )             {                 _tprintf(TEXT("(%d) %s\n"), 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 =http://www.mamicode.com/ MAX_VALUE_NAME; 18     BYTE byteData[MAX_VALUE_NAME];19     DWORD dwData=http://www.mamicode.com/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 =http://www.mamicode.com/ MAX_VALUE_NAME; 40             achValue[0] = \0; 41             dwData=http://www.mamicode.com/MAX_VALUE_NAME;42             byteData[0] = \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

 

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