Chinaunix首页 | 论坛 | 博客
  • 博客访问: 337215
  • 博文数量: 64
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 589
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-08 15:50
文章分类

全部博文(64)

文章存档

2015年(52)

2014年(3)

2013年(9)

我的朋友

分类: WINDOWS

2015-07-01 09:56:37

 前言:刚刚到了一个新公司,学习MFC。说来可笑,一直在Windows下开发软件,而且一直用着C++,而我竟然不会MFC。呵呵,无所谓了,反正学就是了。学习了一段时间,公司需要一个小工具,看着闲着无聊的我就让我做这个小工具。需求不是很复杂,获取Windows系统的一系列信息,诸如系统版本,CPU速度,内存大小,已安装的软件,正在运行的进程。这个小工具做了一周左右,算是完成了吧。这这里就把自己学习到的东西记录下来。如果,有和我一样对于这些基本操作不熟悉的人,可以看看。

 这一篇先记录一些基本操作的使用。首先是注册表的操作:
用Windows系统的时间也不短了,平时如果手动杀毒也会用到注册表。但在接触到注册表之后我才发现,windows几乎将所有的信息基本都记录在了注册表中。闲话少说,先列出我用的注册表操作。

1.
打开注册表中的某一项:

WINADVAPI LSTATUS APIENTRY RegOpenKeyEx (HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);

第一个参数是就是注册表的五大类如:HKEY_CLASS_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,
HKEY_USERS, HKEY_CURRENT_CONFIG.
第二个参数是要打开的注册表项的其余路径:如要打开HKEY_CURRENT_USER\Software\Microsoft的话就
填上Software\\Microsoft.[注意\\,因为\需要转义]
第三个参数是根据MSDN上所说:must be zero.
第四个参数是读写模式,是个枚举值有很多查MSDN好了,我主要用到的就是KEY_READ
第五个参数就是你要把这个想保存在一个HKEY中,所以先定义好。
举个小例子:
比如要打开HKEY_CURRENT_USER\Software\Microsoft,就这样写:

HKEY hSubKey;
LONG lRet = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft"), 0, KEY_READ, &hSubKey);
if(ERROR_SUCESS == hSubKey)
{
    //成功
}
else
{
    //失败
}

刚才忘说返回值了,如果返回值为0的话就说明成功了。

2.获取一个项目下的键值

LONG RegQueryValueEx(
  HKEY hKey, // handle to key
  LPCTSTR lpValueName, // value name
  LPDWORD lpReserved, // reserved
  LPDWORD lpType, // type buffer
  LPBYTE lpData, // data buffer
  LPDWORD lpcbData // size of data buffer
);

从MSDN上拷贝来的解释,我想已经解释的听详细了,那就举个例子吧。
假如要获取HKEY_CURRENT_USER\Software\Microsoft下一个叫DisplayName的类型为REG_SZ的键值
那么请先写上一个函数的示例代码,如果打开成功了,那么就写:

DWORD dwType = REG_SZ;
DWORD dwBufferSize = 256;
CString strKeyValue;
LONG lRet = RegQueryValueEx(hSubKey, _T("DisplayName"), 0, &dwType, (BYTE*)strKeyValue.GetBuffer(dwBufferSize), &dwBufferSize)

如果返回值lRet为0则说明成功了。但这里我说明一点,在这里我获取的Key Value的变量类型是CStirng,
在写代码时如果这么写很方便,但是在获取值后,如果再对这个CString进行操作就会有问题。根据我调试的结果可以看出,这个CString的变量保存的字符串没有一null结尾从而导致对这个变量进行的如字符串连接这种操作会认为这个CString是一个空的字符串。我不知道是因为我机器的原因导致的这个问题还是在MFC中的操作都是这样。至少在OpenFileDialog中利用CString获取的文件路径也是这样的。所以,如果各位遇到了这个问题请注意。
我解决这个问题的方法有两种:1.用一个TCHAR数组来代替这个CString获取Key Value。2.用另一个CString将这个字符串拷贝进来,在我的程序中使用的都是Format函数。

3.枚举一个项目下的所有子项目:

LONG RegEnumKeyEx(
  HKEY hKey, // handle to key to enumerate
  DWORD dwIndex, // subkey index
  LPTSTR lpName, // subkey name
  LPDWORD lpcName, // size of subkey buffer
  LPDWORD lpReserved, // reserved
  LPTSTR lpClass, // class string buffer
  LPDWORD lpcClass, // size of class string buffer
  PFILETIME lpftLastWriteTime // last write time
);

这也是从MSDN中Copy过来的解释,下面直接上代码,比如我们要枚举HKEY_CURRENT_USER\Software\Microsoft下所有子项目:

DWORD dwIndex = 0;
CString strKeyName;
DWORD dwNameSize = 256;

LONG lRet = RegEnumKeyEx(hSubKey, dwIndex, strKeyName.GetBuffer(dwNameSize ), &dwNameSize, 0, NULL, NULL, NULL);
while(ERROR_SUCCESS == lRet)
{
    dwIndex++;
    dwNameSize = 256;
    lRet = RegEnumKeyEx(hSubKey, dwIndex, strKeyName.GetBuffer(dwNameSize ), &dwNameSize, 0, NULL, NULL, NULL);
}

解释一下上面的代码:
dwIndex是枚举用的索引,注册表的枚举和数组一样是从0开始的。
strKeyName是用来保存枚举出来的子项目的名字
dwNameSize和第二示例代码的意义是一样的
函数调用完毕后需要考察返回值,如果返回值为0说明这个项目下有子项,如果不为0一般有两种可能一种是这个子项的名字长度大于你预定的长度在上面代码中是256,另一种就是这个项目下面没有子项。
在取得第一个子项后需要继续向下检索,所以需要dwIndex++,而且因为在函数调用中dwNameSize会被改写,所以需要重新为它赋值[切记这一点否则在接下来的枚举中可能会失败],然后就是继续获取下一项,知道获取完毕为止。
----------------------------------------------------------------------------------
接下来介绍如何通过注册表获取CPU的个主频,以及通过注册表获取本机已经安装的软件。

1.CPU的主频:
 在Windows注册表下保存CPU主频的位置在:
 HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0
 的名为"~MHz"的键中。当然0表示第一个CPU,如果你有两个CPU也可以继续读下去如果有1、2....这些项
 就可以把其他CPU的速度读出来了。
 下面是我写的代码:
 

DWORD GetProcessorSpeed()
{
    HKEY hKey;
    DWORD dwType = REG_DWORD, dwSize = sizeof(DWORD);
    DWORD dwCpuSpeed;
    //Open the appropriate registry key

    LONG lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
             _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
             0, KEY_READ, &hKey);
    if(ERROR_SUCCESS != lRet)
    {
        return 0;
    }
    lRet = RegQueryValueEx(hKey, _T("~MHz"), NULL,
                            &dwType, (BYTE*)&dwCpuSpeed, &dwSize);
    RegCloseKey(hKey);

    if(ERROR_SUCCESS != lRet)
    {
        return 0;
    }
    return dwCpuSpeed;
}

哦,对了在Open一个Key使用完毕后不要忘了用RegCloseKey(HKEY hKey)来关闭这个Key。

2.已安装的软件列表:
  在Windows注册表中有两个位置保存这已经安装的软件:
  HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
  HKEY_LOCAL_MACHINE\
Software\Microsoft\Windows\CurrentVersion\Uninstall
  前者下面一般不会有什么子项的,但是比如Google Chrome浏览器的内容就是记录在这个下面的。
  还有一点是我对比Windows软件类表和360软件管家得到的一个规律。
  就是一个子项中如果包含一个叫SystemComponent的键(REG_DWORD)类型的而且它的值是0x00000001
  的话可以不用在软件列表中列出它来,因为这个项可能是某个软件的组件而不是一个独立的软件。当然,
  这也是有例外的,比如Office Plus 2007这一项就含有SystemComponent项而且值是1,但是Windows
  和360的软件管家仍然把它给列出来了。
  由于这个代码比较长就不列出来了。

阅读(2067) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~