There's always been a fight over an optimal way to detect bitness of an OS. Most of the time, getting system information is considered to be solved using interop services or P/Invoke. For this, the methodology followed is as shown below:
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;
}
}
Actually there's a simple way to do that in C#. C# provides a very useful struct IntPtr
.
64-Bit Vs 32-Bit w.r.t Pointer
We all know that the size of an
Pointer on a 32-bit
machine compiled program is 4-Bytes. The size changes on a 64-Bit compiled program and becomes 8-bytes.
Then why not compare the size of Integer. Pointer is nothing but an Integer and IntPtr
serves the same for us in C#.
The following example shows the simple usage of
IntPtr
.
(UPDATE: As Win64 follows LLP64 Model (For more informarion on LLP64 model please follow
Technet Article[
^]) as corrected by codeproject member
Ajay Vijayvargiya[
^])
if(IntPtr.size == 4)
{
}
else
{
}
Previous code checks whether the program is running in 32-bit or 64-bit mode. This doesn't inform OS bitness.
If using C++/Win32:
IntPtr
is not available in C++. Rather sizeof(int)
does the same.
BOOL Is64BitOS()
{
BOOL bIs64Bit = FALSE;
#if defined(_WIN64)
bIs64Bit = TRUE;
#elif defined(_WIN32)
typedef BOOL (WINAPI *LPFNISWOW64PROCESS) (HANDLE, PBOOL);
LPFNISWOW64PROCESS pfnIsWow64Process = (LPFNISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process");
if (pfnIsWow64Process)
pfnIsWow64Process(GetCurrentProcess(), &bIs64Bit);
#endif
return bIs64Bit;
}
There's one more distinctive feature a 64-Bit OS supports: "Virtualization".
Virtualization (Windows Vista and 7 x64 Platform only)
Virtualization technologies are used by Windows Vista and 7 x64 platform only. These act like virtual machines just like VMWare or similar apps. The advantage here is to run legacy apps such s 32-bit apps. Running 32-Bit apps on 64-Bit OS becomes difficult without virtualization as such applications are usually not written to co-exist within a single execution environment.
64-Bit applications are never run virtualized, nor do 32 or 64-Bit services and drivers. Virtualization becomes active when running legacy 32-bit interactive apps under WOW64.
So if the OS supports virtualization, then it got to be 64-Bit.
You can use the following code to check whether the app is running as virtualized:
[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))
{
string s = "Win32 error " +
Marshal.GetLastWin32Error().ToString();
throw new Exception(s);
}
if(info != 0)
virtualized = true;
return virtualized;
}
if(IsVirtualized(WindowsIdentity.GetCurrent().Toke n))
Thanks to
Luc Pattyn[
^] and
Ajay Vijayvargiya[
^] to point out the errors. :)