65.9K
CodeProject 正在变化。 阅读更多。
Home

32 位或 64 位操作系统??

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (9投票s)

2010 年 9 月 7 日

CPOL

2分钟阅读

viewsIcon

78733

一种在程序中检测操作系统位数的简单方法。(提供了 C# 和 C++ 示例)

一直以来,都存在关于检测操作系统位数的最佳方法的争论。大多数情况下,获取系统信息被认为可以通过互操作服务或 P/Invoke 来解决。为此,所遵循的方法如下所示
public enum Platform
    {
      X86,
      X64,
      Unknown
    }

    internal const ushort PROCESSOR_ARCHITECTURE_INTEL = 0;
    internal const ushort PROCESSOR_ARCHITECTURE_IA64 = 6;
    internal const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9;
    internal const ushort PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;

    [StructLayout(LayoutKind.Sequential)]
    internal struct SYSTEM_INFO
    {
      public ushort wProcessorArchitecture;
      public ushort wReserved;
      public uint dwPageSize;
      public IntPtr lpMinimumApplicationAddress;
      public IntPtr lpMaximumApplicationAddress;
      public UIntPtr dwActiveProcessorMask;
      public uint dwNumberOfProcessors;
      public uint dwProcessorType;
      public uint dwAllocationGranularity;
      public ushort wProcessorLevel;
      public ushort wProcessorRevision;
    };

    [DllImport("kernel32.dll")]
    internal static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);

    [DllImport("kernel32.dll")]
    internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);

    public static Platform GetPlatform()
    {
      SYSTEM_INFO sysInfo = new SYSTEM_INFO();

      if(System.Environment.OSVersion.Version.Major > 5 ||
    (System.Environment.OSVersion.Version.Major == 5 && System.Environment.OSVersion.Version.Minor >= 1))
      {
         GetNativeSystemInfo(ref sysInfo);
      }
      else
      {
         GetSystemInfo(ref sysInfo);
      }

      switch(sysInfo.wProcessorArchitecture)
      {
    case PROCESSOR_ARCHITECTURE_IA64:
    case PROCESSOR_ARCHITECTURE_AMD64:
      return Platform.X64;

    case PROCESSOR_ARCHITECTURE_INTEL:
      return Platform.X86;

    default:
      return Platform.Unknown;
      }
    }
实际上,在 C# 中实现这一点很简单。C# 提供了一个非常有用的结构体 IntPtr

64 位与 32 位关于指针

我们都知道,在 32 位机器上编译的程序中,指针的大小为 4 字节。在 64 位编译的程序中,大小会发生变化,变为 8 字节。那么为什么不比较整数的大小呢?指针本质上就是一个整数,而 IntPtr 在 C# 中为我们提供了相同的功能。以下示例演示了 IntPtr 的简单用法。(更新:由于 Win64 遵循 LLP64 模型(有关 LLP64 模型的更多信息,请参阅 Technet 文章[^]),正如 CodeProject 成员 Ajay Vijayvargiya[^] 指出的那样)
if(IntPtr.size == 4)
{
   //Your logic for 32-Bit.
}
else
{
  // Your logic for 64-Bit.
}
之前的代码检查程序是在 32 位还是 64 位模式下运行。这并不能告知操作系统的位数。如果使用 C++/Win32:IntPtr 在 C++ 中不可用。 相反,sizeof(int) 具有相同的功能。
BOOL Is64BitOS()
{
	BOOL bIs64Bit = FALSE;

	#if defined(_WIN64)

	bIs64Bit = TRUE;  // 64-bit programs run only on Win64

	#elif defined(_WIN32)

	// Note that 32-bit programs run on both 32-bit and 64-bit Windows

	typedef BOOL (WINAPI *LPFNISWOW64PROCESS) (HANDLE, PBOOL);
	LPFNISWOW64PROCESS pfnIsWow64Process = (LPFNISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process");

	if (pfnIsWow64Process)
		pfnIsWow64Process(GetCurrentProcess(), &bIs64Bit);

	#endif

	return bIs64Bit;
}
64 位操作系统支持另一个显著的功能:“虚拟化”。

虚拟化(仅适用于 Windows Vista 和 7 x64 平台)

虚拟化技术仅由 Windows Vista 和 7 x64 平台使用。它们充当虚拟机,就像 VMWare 或类似应用程序一样。这里的优势是运行遗留应用程序,例如 32 位应用程序。在没有虚拟化的情况下,在 64 位操作系统上运行 32 位应用程序会变得困难,因为这些应用程序通常没有被编写为在单个执行环境中同时存在。64 位应用程序绝不会被虚拟化运行,32 位或 64 位服务和驱动程序也不会。虚拟化在 WOW64 下运行遗留 32 位交互式应用程序时变为激活状态。因此,如果操作系统支持虚拟化,那么它一定是 64 位。您可以使用以下代码来检查应用程序是否正在以虚拟化方式运行
[DllImport("advapi32.dll", EntryPoint = "GetTokenInformation",
SetLastError = true)]
static extern bool GetTokenInformationNative(
IntPtr TokenHandle,
int TokenInformationClass,
ref int  TokenInformation,
int TokenInformationLength,
out int ReturnLength);

public bool IsVirtualized(IntPtr token)
{
    bool virtualized = false;
    int len = 4;
    int info = 0;
    if (!GetTokenInformationNative(token, 24, ref info, len, out
    len)) // 24 = TokenVirtualizationEnabled
    {
       string s = "Win32 error " +
       Marshal.GetLastWin32Error().ToString();
       throw new Exception(s);
    }
    if(info != 0)
       virtualized = true;
    return virtualized;
}

// usage...

if(IsVirtualized(WindowsIdentity.GetCurrent().Toke  n))
// better add a manifest to your application if you end here ;-)
感谢 Luc Pattyn[^] 和 Ajay Vijayvargiya[^] 指出错误。:)
© . All rights reserved.