Visual C ++ RegGetValue()在程序中失败,它不应该

时间:2014-09-26 22:17:27

标签: c++ visual-c++ registry

我正在使用Visual C ++ 2008 Express创建一个C ++程序,它从注册表中获取特定应用程序的路径,显示已安装的列表,允许用户选择一个进行配置,然后启动所选应用程序。

该程序应该使用RegGetValue(来自windows.h)检索(当前)三个应用程序的路径。

虽然它适用于应用程序n°1和3,但它以app n°2失败。

处理注册表的源代码部分可在Pastebin上使用:http://pastebin.com/9X2hjGqh

当我添加一个cout以获得函数的返回时,我得到错误n°234(ERROR_MORE_DATA)。


RegGetValue语法:

LONG WINAPI RegGetValue(
  _In_         HKEY hkey,
  _In_opt_     LPCTSTR lpSubKey,
  _In_opt_     LPCTSTR lpValue,
  _In_opt_     DWORD dwFlags,
  _Out_opt_    LPDWORD pdwType,
  _Out_opt_    PVOID pvData,
  _Inout_opt_  LPDWORD pcbData
);

此处完整参考:http://msdn.microsoft.com/en-us/library/ms724875(v=VS.85).aspx

2 个答案:

答案 0 :(得分:0)

ERROR_MORE_DATA表示您传递给RegGetValue的其中一个缓冲区不足以存储您RegGetValue提供给您的数据。当你得到这个退出代码时,你需要循环并重新分配这里提供的缓冲区。

例如:

LONG result = ERROR_MORE_DATA;
DWORD dataLength = /* some reasonable default size */ 255;
unique_ptr<char[]> buffer;
while (result == ERROR_MORE_DATA)
{
    buffer.reset(new char[dataLength]);
    result = RegGetValueW(
        hKey,
        L"Subkey",
        L"Value",
        0,
        nullptr,
        buffer.get(),
        &dataLength
        );
}

if (result != ERROR_SUCCESS)
{
    // Handle the error
}

答案 1 :(得分:0)

有一点突出的是你这么做的所有电话:

RegGetValue(hKey, NULL, "PATH", RRF_RT_ANY, NULL, (PVOID)&ValueBuffer, &BufferSize);

请注意,最后一个参数是&BufferSize。这是[in, out]参数。在进入之前将其设置为缓冲区的大小,并将值更改为在出路时读入缓冲区的字符数。这就是docs关于RegGetValue(以及其他类似的Reg)函数的说法:

  

pcbData [in,out,optional]   指向变量的指针,该变量指定pvData参数指向的缓冲区大小(以字节为单位)。函数返回时,此变量包含复制到pvData的数据大小。

因此,当您调用RegGetValue时,它从8192(BUFFER)开始,但在第一次调用后,它被读取的字符数覆盖。

在每次调用传递&amp; BufferSize的RegGetValue之前,你应该这样做:

BufferSize = BUFFER

我也注意到你有:

#define BUFFER 8192

char ValueBuffer[255];
DWORD BufferSize = BUFFER;

您不应该将ValueBuffer设置为至少ValueBuffer[BUFFER]而不是ValueBuffer[255]吗?

同样,您的代码只支持8192字节缓冲区。如果注册表中的Value键长于该值,则返回ERROR_MORE_DATA。我假设您的代码没有预期8192之外的任何内容。您可以使用RegQueryInfoKey并提前动态分配足够的空间来确定Value键的前端大小。