在运行时正确检查Windows是否为64位的方法是什么?(C++)

7
bool Win64bit = (sizeof(int*) == 8) ? 1 : 0;

我需要这样做才能使我的应用程序正确地使用Windows注册表功能(或者我需要这样做吗?)。

那么,我现在的做法正确吗?


2
如果你将它放在布尔值中,那么没有必要使用"?1:0"这一部分。(其他部分我不确定。) - Chris Burt-Brown
1
尽量避免绕过注册表虚拟化,除非极少数情况下确实需要。 - Hans Passant
您的意思是什么?我想确保我的应用程序也可以在64位Windows中使用注册表,这就是为什么我需要知道当前运行程序的版本,以便选择正确的注册表函数(它们在32位和64位上使用不同的函数)。 - Newbie
请查看我下面关于注册表重定向的评论。 - Igor Korkhov
2
"bool Win64bit = (sizeof(int*) == 8) ? 1 : 0;" 可以告诉你当前程序是否编译为64位。但它并不能告诉你运行该程序的Windows操作系统的位数。 - ytw
4个回答

16

以下是 Raymond Chen 在他的博客中建议的内容:https://devblogs.microsoft.com/oldnewthing/20050201-00/?p=36553

BOOL Is64BitWindows()
{
    #if defined(_WIN64)
        return TRUE;  // 64-bit programs run only on Win64
    #elif defined(_WIN32)
        // 32-bit programs run on both 32-bit and 64-bit Windows
        // so must sniff
        BOOL f64 = FALSE;
        return IsWow64Process(GetCurrentProcess(), &f64) && f64;
    #else
        return FALSE; // Win64 does not support Win16
    #endif
}

这看起来不错,虽然我没有完全理解逻辑,但 BOOL f64 = FALSE; 是不是没用的?BOOL f64; 不应该已经足够了吗? - Newbie
4
这很麻烦,因为在旧版的Windows系统中,kernel32.dll没有导出IsWow64Process()。这会导致程序无法运行。可以使用GetProcAddress()来解决。 - Hans Passant
你在谈论哪些旧版本?Win95?Win98? - Newbie
@新手:nobugz是正确的,为了使上面的代码更加健壮,你应该使用类似这样的东西:“fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");如果(fnIsWow64Process != NULL) { if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { // 处理错误 } }" - Igor Korkhov
@新手:你说的是哪些旧版本?它从WinXP SP2开始导出。 - Igor Korkhov

7
不,这不可能作为一个运行时检查,因为在你选择将程序编译为32位或64位的点上,sizeof(int*)已经在编译时固定,一旦编译完成,无论在哪个平台上运行,检查结果都是相同的。
然而,由于64位程序不能在32位平台上运行,你会发现你的检查在编译时可以正确地工作,而且不需要修改:
如果你将程序编译为64位,你的程序将使用64位API,因为你的代码如上所述,并且将在64位版本的Windows上正确地工作。它将无法在32位的Windows上运行,因此你没有机会在32位版本的Windows上意外地使用64位API。
v++ platform == 64-bit => sizeof(int*) == 8 => use 64-bit API
AND
( windows platform == 64-bit => 64-bit API works
  OR
  windows platform == 32-bit => program does not run )

如果你以32位模式编译程序,程序将正确使用32位API,在64位Windows平台上的32位兼容模式下工作,并且显然可在32位平台上工作。

v++ platform == 32-bit => sizeof(int*) == 4 => use 32-bit API
AND
( windows platform == 64-bit => 32-bit API works using compatibility mode
  OR
  windows platform == 32-bit => 32-bit API works )

如果您真的想从32位程序访问64位API,我敢说有API可以做到这一点,但我不确定您是否希望这样做。

我只需要知道使用RegDeleteKeyEx()还是RegDeleteKey()中的哪一个函数,这就是为什么我需要进行此检查。即使我只需要一个函数,该函数仍然需要根据操作系统选择不同的值:KEY_WOW64_32KEY或KEY_WOW64_64KEY...所以如果我不知道如何获取Windows版本,我就会陷入困境。 - Newbie
1
@新手:你确定你需要知道这个吗?我的意思是,你真的需要删除特定的WOW64_64_KEY吗?因为如果不是的话,值得一提的是WoW64使用了一个注册表重定向器,它通过在WOW64上为32位和64位应用程序提供独立的逻辑视图来隔离它们的关键部分。 - Igor Korkhov
哦,那我可以直接使用32位注册表函数吗?64位的Windows系统能够正确处理它吗? - Newbie

4
此外,可以使用IsWow64Process来检查是否在64位Windows机器上以WoW64仿真运行的32位进程(sizeof(void*)==4)。

4
编译器不知道。至少如果您想找出自己是否在64位Windows上运行,它是不知道的。 - Alexander Gessler
我认为每个回答都从不同的角度回答了这个问题:+1。 - Alex Brown
3
编译器不知道应用程序是否在64位机器上运行。 - John Dibling
在文档中:「如果进程是在64位Windows下运行的64位应用程序,则该值也设置为FALSE。」这是否意味着,如果我在64位机器上编译并在64位机器上运行程序,那么我的程序会认为它是32位Windows?我不明白在这种情况下返回false的意义是什么...顺便说一句,我不希望编译器知道,我需要在运行时检查。 - Newbie
如果您正在编译64位程序,则sizeof(void*)==8成立。在这种情况下,无需调用IsWow64Process - Alexander Gessler
1
@John - 是的,它知道,它正在生成64位代码。包含64位机器码的程序保证无法在32位操作系统上运行。 - Hans Passant

0
这里还有另一种方法: GetSystemWow64Directory - "检索 WOW64 使用的系统目录的路径。该目录不存在于 32 位 Windows 上。" 和 "在 32 位 Windows 上,该函数总是失败,并将扩展错误设置为 ERROR_CALL_NOT_IMPLEMENTED。" 关于 IsWow64Process,我个人不确定它的用法,因为在 MSDN 中对 IsWow64Process 的描述中有这样的文本:"请注意,此技术并不是一种可靠的方法来检测操作系统是否为 Windows 的 64 位版本,因为当前版本的 32 位 Windows 中的 Kernel32.dll 也包含此函数。"

1
我认为你误解了。他们提到检查IsWow64Process是否存在作为一种检测位数的方法。你还需要调用它。 - Andreas Haferburg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接