C - RegQueryValueEx 有时在发布版本中

Min*_*s97 3 c registry debugging winapi release

这真让我抓狂。我正在 Visual Studio 2012 上编译我的项目。我想REG_BINARY使用RegOpenKeyExRegQueryValueEx调用读取注册表项。在调试(多线程调试)模式下,一切正常。但是,在发布(多线程​​)模式下,RegQueryValueEx会经常失败并显示错误代码ERROR_MORE_DATA。这是我正在使用的代码:

HKEY keyHandle;
TCHAR lpData[1024];

DWORD lpcbData;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle) != ERROR_SUCCESS){
    MessageBox(NULL, L"fail", L"title", MB_OK);
    return NULL;
} else if (RegQueryValueEx(keyHandle, L"DigitalProductId", NULL, NULL, (LPBYTE)lpData, &lpcbData) != ERROR_SUCCESS){
    MessageBox(NULL, L"fail!", L"title", MB_OK);
    return NULL;
}

MessageBox(NULL, L"success", L"title", MB_OK);
Run Code Online (Sandbox Code Playgroud)

小智 5

根据 RegQueryValueEx 的定义,lpcbData 既是In参数,也是Out参数。也就是说,RegQueryValueEx 读取它并写入它。它抱怨是因为您在传递它时没有先使用缓冲区的大小初始化它,在您的情况下是 1024(我还建议您根据 API 的要求将 TCHAR 更改为 BYTE;稍后您可以将其转换为 Unicode 字符串)。

在调用该函数之前尝试将其设置为 1024。如果失败与ERROR_MORE_DATA,那么你的缓冲区不够大-换句话说,该注册表项字符串太长-你可以用NULL参数首先定义它包含多个字符,或者更好的是,调用函数而不是缓冲区,您将在 lpcbData 中返回所需的缓冲区大小。然后,您可以在堆上分配所需的缓冲区。希望这可以帮助!

  • @Mints97 回答让你发疯的问题:它似乎在调试版本中工作,因为调试版本使用位模式(0xcccccccc)初始化内存,以便更容易地发现未初始化的内存。该值足以一次性读取您的注册表数据。它也大于您的实际缓冲区大小。在 Release 中,未初始化的内存包含先前写操作遗留在那里的任何内容。之前未写入的内存保持值 0。将 0 作为 lpcbData 参数传递给非空的 `lpData` 不可避免地会导致 `ERROR_MORE_DATA`。 (3认同)