windows注册表重定向问题
通过windows函数SHGetValueW打开注册表的指定路径并查找相对用的Value时,函数返回错误代码 = 2(系统找不到指定的文件),这就牵扯出了关于windows注册表重定向的问题。
为什么会有重定向这个问题呢,是为了将32位程序和64位程序分离开。在64位平台上运行32位程序的模拟器被称为WOW64。WOW64是”Windows 32 on Windows 64”的简称,它在系统层中另提供了一层,以支持老式的32位程序。所以说32位的程序和64位的程序就被分开存放了。
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
这是64位程序存放的路径,但是当用SHGetValueW函数调用时,因为重定向问题系统会自动将路径重新定位到下面的32位程序存放的路径中。
HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall
所以就会出现找不到指定文件这一错误。
解决办法
可以调用函数Wow64DisableWow64FsRedirection临时性关闭系统注册表重定向问题,这时系统就能正常的进入64位程序的安装路径中了。但是在使用结束时要用函数Wow64RevertWow64FsRedirection来恢复系统注册表重定向。
用法和常见问题
Wow64DisableWow64FsRedirection和Wow64RevertWow64FsRedirection函数明确说明了只能在xp64位以上的系统使用。
使用方法:
Wow64DisableWow64FsRedirection(0); //禁用重定向
...
....
....
Wow64RevertWow64FsRedirection(0); //恢复重定向
但是在使用时我们经常会遇到这种情况,写的程序需要重定向,但是要兼容所有系统,比如xp32位,如果现在不仅以操作就会出现在xp32中运行 连接不到当前函数的问题,即使你没有去调用这个函数。因为他会在你运行的时候将需要的DLL和函数添加进去(解释的不是很合理,《程序员自我修养》上有说, 忘得差不多了)。所以我们要在调用前判断当前函数是否支持当前操作系统,也就是说是否在DLL里有这个函数,有则链接添加,没有就跳过。
声明
WINBASEAPI
BOOL
WINAPI
Wow64DisableWow64FsRedirection (__out PVOID *OldValue);
WINBASEAPI
BOOL
WINAPI
Wow64RevertWow64FsRedirection ( __in PVOID OlValue);
BOOL Is64BitOs()
{
static BOOL isWow64 = FALSE;
static BOOL valid = FALSE;
typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process);
LPFN_ISWOW64PROCESS fnIsWow64Process;
#ifdef _WIN64
return TRUE;
#endif
if (valid)
return isWow64;
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandleA("kernel32"), "IsWow64Process");
if (fnIsWow64Process != NULL)
if (!fnIsWow64Process (GetCurrentProcess(), &isWow64))
isWow64 = FALSE;
valid = TRUE;
return isWow64;
}
使用:
PVOID OldValue;
HINSTANCE hlibrary;
typedef int (__stdcall * Wow64DisableWow64FsRedirection)(LPVOID);
typedef int (__stdcall * Wow64RevertWow64FsRedirection)(LPVOID);
Wow64DisableWow64FsRedirection f_Wow64DisableWow64FsRedirection = NULL;
Wow64RevertWow64FsRedirection f_Wow64RevertWow64FsRedirection = NULL;
//链接当前DLL,因为函数在当前DLL中
hlibrary = LoadLibrary(_T("Kernel32.dll"));
//在当前DLL中遍历调用的函数
f_Wow64DisableWow64FsRedirection = (Wow64DisableWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64DisableWow64FsRedirection"));
if (f_Wow64DisableWow64FsRedirection && (Is64BitOs()))
{
//但前函数存在
f_Wow64DisableWow64FsRedirection(&OldValue);
//禁用重定向
f_Wow64RevertWow64FsRedirection = (Wow64RevertWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64RevertWow64FsRedirection"));
////////////////////////////
...
...
...
...
////////////////////////////
//恢复重定向
if(f_Wow64RevertWow64FsRedirection)
{
f_Wow64RevertWow64FsRedirection (OldValue);
}
}