C++ RegGetValue 问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6308426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:53:33  来源:igfitidea点击:

RegGetValue Question

c++winapiregistry

提问by Josh

I'm trying to write(what I thought would be) a simple script in C++ to search through the registry(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall specifically) and return the value of the DisplayName value.

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

I have gone through the MSDN docs, and hours of searching on google, unfortunately I'm stuck.

我已经浏览了 MSDN 文档,并在谷歌上搜索了数小时,不幸的是我被卡住了。

#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);
}

Now, I need to be able to append achKey to the 2nd parameter of RegGetValue, so that it grabs the correct values when looping through each subkey.

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

I've tried a million different things, unfortunately my experience in C++ is pretty limited and my google skills apparently need some work as well.

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

Edit: achKey is the name of the key: Ex: NVIDIA Drivers

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

So when appended, the 2nd param should read:

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

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

Here's the MSDN reference on RegGetValue: http://msdn.microsoft.com/en-us/library/ms724868%28v=vs.85%29.aspx

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

I have also tried something like:

我也尝试过类似的事情:

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

It will compile, but then when run, it crashes.

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

回答by uesp

There are two main issues with your original code that I can see:

我可以看到您的原始代码有两个主要问题:

  1. Mixing Unicode/ACSII Strings: From your comments it appears you are compiling the project with Unicode strings but you are using a char value[255]. Use a wchar_tor TCHARinstead of char. the RegGetValue()function will be automatically 'forwarded' to the RegGetValueW()or RegGetValueA()functions depending on the project Unicode settings. If you wish to force a particular character set you can use those functions directly but it is generally better to just use the RegGetValue()function directly.
  2. Buffer Overflow:You are use a 255 element char buffer but passing the buffer's size as 8192. If the registry key is more than 255 bytes (not characters) then you'll overflow that buffer and bad things will happen. Make sure you pass the exact buffer size or smaller. Also be aware of the differences between bytes and characters with Unicode strings. Some functions may expect or return a buffer size in bytes and some in characters.
  1. 混合 Unicode/ACSII 字符串:从您的评论看来,您正在使用 Unicode 字符串编译项目,但您使用的是char value[255]. 使用wchar_tTCHAR代替char。该RegGetValue()函数将根据项目 Unicode 设置自动“转发”到RegGetValueW()RegGetValueA()函数。如果您希望强制使用特定字符集,您可以直接使用这些函数,但通常最好RegGetValue()直接使用该函数。
  2. 缓冲区溢出:您使用了 255 个字符的缓冲区,但将缓冲区的大小作为 8192 传递。如果注册表项超过 255 个字节(不是字符),那么您将溢出该缓冲区,并且会发生不好的事情。确保传递确切的缓冲区大小或更小。还要注意字节和字符与 Unicode 字符串之间的差异。某些函数可能期望或返回以字节为单位的缓冲区大小,而某些以字符为单位。

The following code is an example of using wide-strings in the manner you desire:

以下代码是以您希望的方式使用宽字符串的示例:

#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");

Edit: LPCWSTR Notes

编辑:LPCWSTR 注释

A LPCWSTRin Windows is simple a pointer to a constant wide string, or more directly a const wchar_t *which is the same thing as a TCHAR *in a Unicode project. Note that if you changed your project to a MultiByte character set then the function declaration of RegGetValue()(and a host of other Windows functions) would change to using a LPCSTRinstead and a TCHARwould simply be a char.

LPCWSTRWindows 中的A是一个指向常量宽字符串的指针,或者更直接的 aconst wchar_t *TCHAR *Unicode 项目中的 a相同。请注意,如果您将项目更改为 MultiByte 字符集,则RegGetValue()(以及许多其他 Windows 函数)的函数声明将更改为使用 aLPCSTR代替,而 aTCHAR将只是char.

The nice thing about using std::string/wstring is that they are directly compatible with a LPCWSTRand a LPCSTR. Thus your call to RegGetValue()can use the std::wstring variables directly like:

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

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

回答by Roddy

I have also tried something like:

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

It will compile, but then when run, it crashes.

我也尝试过类似的事情:

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

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

That's because you are trying to concatenate something onto a literal string, so the best that will happen is you will trample over random areas of your application. I'm a little surprised it compiles without errors or warnings, as the literal string would be const...?

那是因为您正在尝试将某些内容连接到一个文字字符串上,因此最好的情况是您将践踏应用程序的随机区域。我有点惊讶它编译没有错误或警告,因为文字字符串将是 const...?

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

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

回答by Jerry Coffin

What you're looking at here is pretty basic string manipulation. Something like:

你在这里看到的是非常基本的字符串操作。就像是:

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

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

If you're using wide strings, you want to use wstring(and wide character literals) instead:

如果您使用宽字符串,则希望使用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(), /* ... */);