RegGetValue问题

时间:2011-06-10 15:19:17

标签: c++ winapi registry

我正在尝试编写(我认为会是)一个简单的C ++脚本来搜索注册表(特别是SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall)并返回DisplayName值的值。

我已经浏览了MSDN文档,并且在Google上搜索了几个小时,不幸的是我被卡住了。

#define BUFFER 8192
char value[255];
DWORD BufferSize = BUFFER;

if(RegGetValue(HKEY_LOCAL_MACHINE,
    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"),
    _T("DisplayName"),
    RRF_RT_ANY,
    NULL,
    (PVOID)&value,
    &BufferSize)
    )
{
    _tprintf(TEXT("(%d) %s - %s\n"), i+1, achKey, value);
}

现在,我需要能够将achKey附加到RegGetValue的第二个参数,以便在循环遍历每个子项时抓取正确的值。

我已经尝试了一百万种不同的东西,不幸的是我的C ++经验非常有限,我的谷歌技能显然也需要一些工作。

编辑: achKey是密钥的名称: 例如:NVIDIA驱动程序

因此,当附加时,第二个参数应为:

SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\NVIDIA Drivers

这是RegGetValue上的MSDN参考: http://msdn.microsoft.com/en-us/library/ms724868%28v=vs.85%29.aspx

我也尝试了类似的事情:

wcscat(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"), achKey)

它会编译,但是当它运行时,它会崩溃。

3 个答案:

答案 0 :(得分:4)

我可以看到原始代码存在两个主要问题:

  1. 混合Unicode / ACSII字符串:从您的评论中看来,您正在使用Unicode字符串编译项目,但您使用的是char value[255]。使用wchar_tTCHAR代替charRegGetValue()函数将自动“转发”到RegGetValueW()RegGetValueA()函数,具体取决于项目的Unicode设置。如果您希望强制使用特定字符集,则可以直接使用这些函数,但通常最好直接使用RegGetValue()函数。
  2. 缓冲区溢出:您使用255个元素的char缓冲区,但将缓冲区的大小传递为8192.如果注册表项超过255个字节(不是字符),那么您将溢出该缓冲区并且坏事会发生。确保传递确切的缓冲区大小或更小。还要注意Unicode字符串的字节和字符之间的差异。某些函数可能期望或返回缓冲区大小(以字节为单位),有些函数以字符形式返回。
  3. 以下代码是以您希望的方式使用宽字符串的示例:

    #include <iostream>
    #include <string>
    
        ...
    std::wstring BaseKey(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"));
    std::wstring achKey(_T("DisplayName"));
    std::wstring NewKey;
    
    NewKey = BaseKey + achKey;
    wcout << NewKey << _T("\n");
    NewKey = BaseKey + _T("AnotherName");
    wcout << NewKey << _T("\n");
    

    编辑:LPCWSTR备注

    Windows中的LPCWSTR是指向常量宽字符串的指针,或者更直接地指向const wchar_t *,这与Unicode项目中的TCHAR *相同。请注意,如果您将项目更改为MultiByte字符集,那么RegGetValue()(以及许多其他Windows函数)的函数声明将更改为使用LPCSTR代替TCHAR只需成为char

    使用std :: string / wstring的好处是它们与LPCWSTRLPCSTR直接兼容。因此,您对RegGetValue()的调用可以直接使用std :: wstring变量,如:

    std::wstring BaseKey(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"));
    std::wstring Value(_T("DisplayName"));
    RegGetValue(HKEY_LOCAL_MACHINE, BaseKey, Value, ...).
    

答案 1 :(得分:0)

  

我也尝试了类似的事情:

wcscat(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"), achKey)
     

它会编译,但是当它运行时,它   崩溃。

那是因为你试图将某些东西连接到一个文字字符串上,所以最好的情况是你会践踏应用程序的随机区域。我有点惊讶它编译没有错误或警告,因为文字字符串将是const ...?

http://msdn.microsoft.com/en-us/library/h1x0y282%28v=vs.80%29.aspx

答案 2 :(得分:-1)

你在这里看到的是非常基本的字符串操作。类似的东西:

std::string path("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
std::string achKey = get_key();

RegGetValueEx(HKEY_LOCAL_MACHINE, (path+achKey).c_str(), /* ... */);

如果您使用的是宽字符串,则需要使用wstring(和宽字符文字):

std::wstring path(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");

std::wstring achKey = get_key(); // some function that gets the key you care about.

RegGetValueEx(HKEY_LOCAL_MACHINE, (path+achKey).c_str(), /* ... */);