【问题标题】:C++ RegEnumValue throws ERROR_MORE_DATAC++ RegEnumValue 抛出 ERROR_MORE_DATA
【发布时间】:2013-07-25 12:33:13
【问题描述】:

我试图从注册表中获取我的所有 comports。 不幸的是,我总是收到 ERROR_MORE_DATA 错误... 我已经尝试让我的缓冲区更大,但它根本无济于事。 这是我的代码:

DWORD registry::regGetValue(char *key, int index)
{
HKEY hKey; 
 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
     DWORD chars = sizeof(key);
     LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
 RegCloseKey(hKey);
 return result;
}

参数为:

char key[512];
int index = 0;

【问题讨论】:

  • sizeof(key) 是 4,因为它是一个指针。将缓冲区的实际大小传递给您的函数并使用它。
  • 非常感谢,完美运行。问题是我总是尝试使用 sizeof() 来获取大小,即使我想获取静态数字的大小。解决方案是:DWORD chars = 512;

标签: c++ winapi registry


【解决方案1】:

缓冲区可能足够大,您只是在对函数的实际大小撒谎。

当您对指针使用sizeof 运算符时,它返回指针的大小,而不是它指向的数组的大小。而且因为key 是作为char* 传递给函数的,所以它只是一个指向数组的指针,而不是数组本身。

您必须将缓冲区的实际大小与指针一起作为参数传递给函数:

DWORD regGetValue(char *key, size_t length, int index)
{
   HKEY hKey; 
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
   DWORD chars = length;
   LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
   RegCloseKey(hKey);
   return result;
}
char key[512];
int index = 0;
regGetValue(key, sizeof(key), index);

sizeof 运算符在这里按预期工作,因为它在数组本身上运行,而不仅仅是指向它的指针。这种方法虽然在 C API 中很常见,但很麻烦。

您可以通过使用自动推断缓冲区大小并将其传递给实际完成工作的内部辅助函数的函数模板来稍微简化调用站点的操作:

// Helper function, implemented as a private member of your class
DWORD regGetValue(char *key, size_t length int index)
{
   HKEY hKey; 
   RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM",0,KEY_ALL_ACCESS,&hKey);
   DWORD chars = length;
   LONG result = RegEnumValue(hKey, index, key, &chars, 0,0,0,0 );
   RegCloseKey(hKey);
   return result;
}

// The public function that you will actually call
template <size_t N>
DWORD regGetValue(char (&key)[N], int index)
{
   return regGetValue(key, N, index);
}
char key[512];
int index = 0;
regGetValue(key, index);  // length determined and passed automatically

之所以有效,是因为您将引用传递给数组,而不是指针。

除此之外,我必须认真质疑您为什么要调用 ANSI 函数并为字符串使用 char*。所有现代 Windows 应用程序都应该是 Unicode。这意味着调用 Windows API 函数的 W 后缀版本并使用 wchar_t* 作为您的字符串类型。确保为您的项目定义了 UNICODE_UNICODE 符号,如果使用错误的类型,您将收到编译时错误。

【讨论】:

    【解决方案2】:

    MSDN 说:如果 lpName 缓冲区太小而无法接收密钥的名称,则函数返回 ERROR_MORE_DATA。在调用RegEnumKeyEx 之前,您可以调用函数RegQueryInfoKey 来确定@​​987654324@ 标识的键的最大子键的大小。 RegQueryInfoKey的用法可以在这里找到:“http://msdn.microsoft.com/en-us/library/windows/desktop/ms724902(v=vs.85).aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      • 1970-01-01
      相关资源
      最近更新 更多