检测 32 位或 64 位 Windows

Posted

技术标签:

【中文标题】检测 32 位或 64 位 Windows【英文标题】:Detect 32-bit or 64-bit of Windows 【发布时间】:2011-10-24 01:47:50 【问题描述】:

我想检测当前的 Windows 操作系统是 32 位还是 64 位。如何使用 C++ 实现它?我不想要处理器类型我想要操作系统的位类型。这是因为您可以在 64 位处理器上安装 32 位操作系统。

【问题讨论】:

可能重复:***.com/questions/1505582/… 他不是在询问代码是用 32 位还是 64 位编译的,而是试图找到已安装的操作系统版本 ***.com/questions/2140619/… 的副本(有更完整的答案)。 【参考方案1】:

要调用的函数是IsWow64ProcessIsWow64Process2。它会告诉您的 32 位应用程序是否在 64 位 Windows 上运行。

如果程序编译为 64 位,它就已经知道了。

【讨论】:

如果该函数存在,就足以表明它是 64 位 Windows,对吧?你甚至不需要调用它。 msdn 说该函数存在并不意味着它是 64 位窗口。 “为了兼容不支持该函数的操作系统,调用GetProcAddress来检测Kernel32.dll中是否实现了IsWow64Process。如果GetProcAddress成功,则调用该函数是安全的。否则,WOW64不存在。注意这个技术是不是检测操作系统是否为 64 位版本 Windows 的可靠方法,因为当前 32 位 Windows 版本中的 Kernel32.dll 也包含此功能。” @GetFree: "如果函数存在,这就足以表明它是 64 位 Windows,对吧?" - 不。IsWow64Process() 存在于 32 - 位版本的 XP SP2 及更高版本。【参考方案2】:

如果您的代码是 64 位且正在运行,则 Windows 是 64 位 - 无需检查。如果您的进程是 32 位,请调用 IsWow64Process() - 32 位进程在 64 位 Windows 上以 WOW64 运行,否则不使用 WOW64。

【讨论】:

调用这个函数会影响我的 32 位进程的虚拟化吗? @Wolf:你能提供更多细节吗? 具体来说,我担心应用程序在调用IsWow64Process() 后可能会丢失HKLM 注册表项(或类似内容)的自动翻译。 @Wolf:AFAIK 这个函数不会改变程序状态——它只是返回一个布尔值,仅此而已。 MSDN 从未提及调用此函数会导致任何程序状态更改。【参考方案3】:
bool getWindowsBit(bool & isWindows64bit)

#if _WIN64

    isWindows64bit =  true;
    return true;

#elif _WIN32

    BOOL isWow64 = FALSE;

    //IsWow64Process is not available on all supported versions of Windows.
    //Use GetModuleHandle to get a handle to the DLL that contains the function
    //and GetProcAddress to get a pointer to the function if available.

    LPFN_ISWOW64PROCESS fnIsWow64Process  = (LPFN_ISWOW64PROCESS) 
GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");

    if(fnIsWow64Process)
    
        if (!fnIsWow64Process(GetCurrentProcess(), &isWow64))
            return false;

        if(isWow64)
            isWindows64bit =  true;
        else
            isWindows64bit =  false;

        return true;
    
    else
        return false;

#else

    assert(0);
    return false;

#endif

【讨论】:

需要这个。 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (句柄, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process; 取自msdn.microsoft.com/en-gb/library/windows/desktop/… 你应该添加你的来源,以避免抄袭的嫌疑。【参考方案4】:

如果你的应用是 32 位应用,你可以使用 IsWow64Process,如果你是在 x64 操作系统上运行,否则它是 32 位

【讨论】:

【参考方案5】:

您需要使用GetNativeSystemInfo。鉴于您希望这可以在 32 位操作系统上运行,您需要使用 LoadLibrary + GetProcAddress 以便您可以处理此功能不可用的情况。所以如果失败了,你就知道它是一个 32 位操作系统。如果没有,SYSTEM_INFO.wProcessorArchitecture 会为您提供真正的处理器类型,而不是模拟的。

【讨论】:

【参考方案6】:

使用GetNativeSystemInfo 函数。它得到一个LPSYSTEM_INFO 参数来得到你想要的。

SYSTEM_INFO结构:

wProcessorArchitecture 已安装操作系统的处理器架构。

【讨论】:

微软的文档是错误的,实际上 wProcessorArchitecture 并没有返回已安装的 OS 处理器架构,而是返回构建应用程序的架构。 @ThreeBit:这个答案很好。你说的GetSystemInfo是真的,这个答案需要GetNativeSystemInfo【参考方案7】:

这是另一种方式:GetSystemWow64Directory - “检索 WOW64 使用的系统目录的路径。该目录在 32 位 Windows 上不存在。”和“在 32 位 Windows 上,函数总是失败,并且扩展错误设置为 ERROR_CALL_NOT_IMPLEMENTED。”

我个人不确定IsWow64Process 的用法,因为在MSDN 中IsWow64Process 的描述中有文字“请注意,这种技术不是检测操作系统是否为64-的可靠方法位版本的 Windows,因为当前 32 位 Windows 版本中的 Kernel32.dll 也包含此功能。”

【讨论】:

这是我见过的最简单的方法【参考方案8】:
bool IsX64win()

    UINT x64test = GetSystemWow64DirectoryA(NULL, 0);
    if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)  return FALSE;
    else return TRUE;

【讨论】:

另一种方法是使用“GetNativeSystemInfo”【参考方案9】:

您可以将 windows 命令systeminfo 作为程序中的进程运行。

#include <stdlib.h>

system("systeminfo");

其中一个返回类别是系统类型。

其输出为:System Type: x86-based PC,或System Type: x64-based PC

这可能是一个比其他人提供的更复杂的解决方案,但我想我会添加它作为一种可能性。 (也许您也在寻找其他信息。)

【讨论】:

我很感激 2.5 年后出现的反对票,并附有解释。如果这不再是一个有效的选项,不要害怕让我知道:) 或者是3年后的那个O-o 嗯,这是一个有效的答案。然而,解析另一个进程的输出并不像调用专门为此目的而设计的IsWow64Process() 函数那么简单。 打印一大堆与 OP 要求无关的系统信息,使用 IsWow64Process() 方法。【参考方案10】:

对较新版本的 Windows 的回答

虽然有几个人和 Microsoft Docs 为此建议了 IsWow64Process2,但我在研究中没有看到任何代码示例。这就是为什么我想将这个答案贡献给社区。​​p>

根据running 32 bit applications documentation page,微软建议在Windows 10 中使用IsWow64Process2 而不是IsWow64Process:

32 位应用程序可以通过调用 IsWow64Process 函数来检测它是否在 WOW64 下运行(如果针对 Windows 10,则使用 IsWow64Process2)。

此功能适用于 Windows 10 版本 1511(客户端)和 Windows Server 2016 及更高版本。

这有两个参数用于返回信息:pProcessMachine 和 pNativeMachine。两者都返回Image File Machine Constants

pProcessMachine 返回有关目标进程是否在 WOW64 模拟器下运行的信息,如果是,它是什么类型的进程。

pNativeMachine 返回有关 Windows 主机体系结构的信息。

使用这两个返回值,可以确定 Windows 是 32 位还是 64 位(这是 OP 要求的),以及进程是否在 WOW64 下运行以及进程是 32 位还是 64 位。

这是我为这些目的编写的一个函数:

BOOL getBits(BOOL& windowsIs32Bit, BOOL& isWOW64, BOOL& processIs32Bit)

  USHORT ProcessMachine;
  USHORT NativeMachine;

  if (!IsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) 
    std::cerr << "IsWOW64Process2 returned FALSE (failed). GetLastError returned: " << GetLastError() << std::endl;
    return FALSE;
  

  if (ProcessMachine == IMAGE_FILE_MACHINE_UNKNOWN) 
    isWOW64 = FALSE;

    if (NativeMachine == IMAGE_FILE_MACHINE_IA64 || NativeMachine == IMAGE_FILE_MACHINE_AMD64 || NativeMachine == IMAGE_FILE_MACHINE_ARM64) 
      windowsIs32Bit = FALSE;
      processIs32Bit = FALSE;

      return TRUE;
    

    if (NativeMachine == IMAGE_FILE_MACHINE_I386 || NativeMachine == IMAGE_FILE_MACHINE_ARM) 
      windowsIs32Bit = TRUE;
      processIs32Bit = TRUE;

      return TRUE;
    

    std::cerr << "Unknown Windows Architecture." << std::endl;
    return FALSE;
  

  windowsIs32Bit = FALSE;
  isWOW64 = TRUE;
  processIs32Bit = TRUE;

  return TRUE;

这是上述函数的一个示例用法:

int main() 

  BOOL windowsIs32Bit;
  BOOL isWOW64;
  BOOL processIs32Bit;

  if (!getBits(windowsIs32Bit, isWOW64, processIs32Bit)) 
    return -1;
  

  std::cout << (windowsIs32Bit ? "Windows is 32 bit" : "Windows is 64 bit") << std::endl;
  std::cout << (isWOW64 ? "This process *is* running under WOW64" : "This process is *not* running under WOW64") << std::endl;
  std::cout << (processIs32Bit ? "This process is 32 bit" : "This process is 64 bit") << std::endl;

  return 0;

我只能测试上述代码的两个场景,因为我在 64 位机器上只有 64 位 Windows。我没有 32 位机器,也没有 32 位 Windows,也没有 ARM 机器。如果有人可以测试其他场景,我将不胜感激有关我所做的设计是否适合他们的反馈。

我写了一个article,更深入地解释了上述代码的工作原理。

【讨论】:

【参考方案11】:

另外最简单的方法是使用sizeof(int *) 检查整​​数指针的大小。

如果为 4,则为 32 位 如果为 8 则为 64 位

【讨论】:

【参考方案12】:

这是一个未记录的方法...

bool _Is64BitOS(void);


bool   _Is64BitOS(void) 
    unsigned int version = *((unsigned int)*)0x7FFE026C;
    unsigned int address = version == 10 ? 0x7FFE0308 : 0x7FFE0300;
//printf("Running %u-bit system",*((void*)*)address ? 32 : 64);

    return (*((void*)*)address ? false,true);
;

【讨论】:

【参考方案13】:
 static bool is64bitOS()
   
      SYSTEM_INFO si;
      GetSystemInfo(&si);

      if((si.wProcessorArchitecture & PROCESSOR_ARCHITECTURE_IA64)||(si.wProcessorArchitecture & PROCESSOR_ARCHITECTURE_AMD64)==64)
      
         return true;
      
      else
      
         return false;
      

   

【讨论】:

除了错误'==64'之外,它也不起作用。对于 32 位应用程序,它不会检测到 64 位操作系统。您应该使用如下所述的“GetNativeSystemInfo”。【参考方案14】:

一个简单的检查是如果 EXE 没有运行,那么它是在 32 位机器上运行的 64 位可执行文件。 64 位机器将始终运行 32 位可执行文件。

来自Microsoft,

大多数为 32 位版本的 Windows 设计的程序都可以在 64 位版本的 Windows。值得注意的例外是许多防病毒软件 程序。

为 32 位版本的 Windows 设计的设备驱动程序不起作用 在运行 64 位版本 Windows 的计算机上。如果你想 安装只有 32 位驱动程序的打印机或其他设备 可用,它不能在 64 位版本的 Windows 上正常工作。

但是,在 Windows 中,您还可以检查 Program Files (x86) 文件夹是否存在,作为另一个简单的检查。无需花哨。

【讨论】:

Err,程序无法运行时如何得出结论? 制作一堆为各种架构和位数编译的 hello-world 程序 - 然后尝试从您的应用程序中执行它们 - 任何子程序将运行表明相关主机的“个性”能够执行。 (您可能能够检测到更多的可运行性功能,例如 .NET 框架支持,例如 .NET 3.0/4.0;这样做时,拥有正确的 QT 库或其他常用库也可能会揭开面纱。)

以上是关于检测 32 位或 64 位 Windows的主要内容,如果未能解决你的问题,请参考以下文章

从用户代理或 Javascript 检测 64 位或 32 位 Windows?

如何根据浏览器在同一页面上嵌入 32 位或 64 位 ActiveX 控件?

在 64 位 Windows 上安装 32 位或 64 位应用程序有啥区别?

对构建 32 位或 64 位感到困惑

如何根据目标机器(32 位或 64 位)有条件地使用 WiX 安装文件?

安装的jvm是64位或32位[重复]