问题 & 解决方案
VS2022 RegOpenKeyEx 返回 2(ERROR_FILE_NOT_FOUND) 最近,把一个 Devcpp 项目复制到 VS 中,发现竟然不能正常运行了。 经过检查 RegOpenKeyEx(HKEY_CURRENT_USER, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey); 返回了 2。 查看 winerror.h 中的定义:系统找不到指定的文件???
#define ERROR_FILE_NOT_FOUND 2L
检查一下注册表,路径没有问题,经过一番折腾,找到了 lpSubKey 参数的问题: 首先官方文档下方给出了提示:RegOpenKeyEx 是一个别名,它会根据是否定义了 UNICODE 宏自动选择 ANSI 版本或者 Unicode 版本。 再看两个可以被选择的函数:
LSTATUS RegOpenKeyExA(
[in] HKEY hKey,
[in, optional] LPCSTR lpSubKey,
[in] DWORD ulOptions,
[in] REGSAM samDesired,
[out] PHKEY phkResult
);
LSTATUS RegOpenKeyExW(
[in] HKEY hKey,
[in, optional] LPCWSTR lpSubKey,
[in] DWORD ulOptions,
[in] REGSAM samDesired,
[out] PHKEY phkResult
);
它们只有 lpSubKey 参数的类型不同,一个是 LPCSTR 一个是 LPCWSTR 分别对应 CHAR* 和 WCHAR*
WCHAR TCHAR CHAR 区别
结论(可在 winnt.h 中查看): CHAR == char WCHAR == wchar_t == unsigned short (vcruntime.h) TCHAR 会根据是否定义 UNICODE 宏自动确定为 CHAR 或 WCHAR。
因此在使用 ANSI 编码的情况下:
const char* lpszSubKey = "SOFTWARE\\regTest";
const CHAR* lpszSubKey = "SOFTWARE\\regTest";
const LPCSTR lpszSubKey = "SOFTWARE\\regTest";
const TCHAR* lpszSubKey = "SOFTWARE\\regTest";
LONG result = RegOpenKeyExA(HKEY_CURRENT_USER, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
同理,在使用 Unicode 编码时:
const WCHAR* lpszSubKey = L"SOFTWARE\\regTest";
const wchar_t* lpszSubKey = L"SOFTWARE\\regTest";
const LPCWSTR lpszSubKey = L"SOFTWARE\\regTest";
const TCHAR* lpszSubKey = L"SOFTWARE\\regTest";
const TCHAR* lpszSubKey = TEXT("SOFTWARE\\regTest");
LONG result = RegOpenKeyExW(HKEY_CURRENT_USER, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
注意:不要将 const char* 类型字符串强制转为 const TCHAR* 错误代码:const TCHAR* lpszSubKey = (const TCHAR*)"SOFTWARE\\regTest"; 当 UNICODE 宏定义存在时,该转换是错误的; 当 UNICODE 宏定义不存在时,该转换是不必要的。 因此,不应用这种方式进行转换。 正确的转换方法是使用 TEXT() 或在字符串前加 L
目前如果试图将const char* 转换为 TCHAR* VS 会报出警告: C6276 在语义上不同的字符串类型之间强制转换。使用无效字符串可能会导致未定义的行为。 但是程序仍能运行,并在 RegOpenKeyEx 产生 ERROR_FILE_NOT_FOUND 错误。
|