码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-01-08 13:06:26      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:

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

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

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

本文链接: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 = 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] = \0; 
41             dwData=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

 

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

标签:

原文地址:http://www.cnblogs.com/wlsandwho/p/4210481.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!