Identifying the CPU architecture type using C#
See the question and my original answer on StackOverflowHere is a piece of code that seems to work (based on P/Invoke); It allows to determine the CPU/Machine architecture, current process architecture and also a given binary file architecture (how it's been compiled):
public enum Architecture
{
Unknown,
x86,
x64,
arm64,
}
public static Architecture ProcessArchitecture
{
get
{
var si = new SYSTEM_INFO();
GetSystemInfo(ref si);
return GetArchitecture(ref si);
}
}
public static Architecture MachineArchitecture
{
get
{
var si = new SYSTEM_INFO();
GetNativeSystemInfo(ref si);
return GetArchitecture(ref si);
}
}
public static Architecture ReadFileArchitecture(string filePath)
{
if (filePath == null)
throw new ArgumentNullException(nameof(filePath));
using (var stream = File.OpenRead(filePath))
{
return ReadFileArchitecture(stream);
}
}
// note .NET dll will come out as x86
public static Architecture ReadFileArchitecture(Stream stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
var length = stream.Length;
if (length < 64)
return Architecture.Unknown;
var reader = new BinaryReader(stream);
stream.Position = 60;
var peHeaderPtr = reader.ReadUInt32();
if (peHeaderPtr == 0)
{
peHeaderPtr = 128;
}
if (peHeaderPtr > length - 256)
return Architecture.Unknown;
stream.Position = peHeaderPtr;
var peSignature = reader.ReadUInt32();
if (peSignature != 0x00004550) // "PE"
return Architecture.Unknown;
var machine = reader.ReadUInt16();
Architecture arch;
switch (machine)
{
case IMAGE_FILE_MACHINE_AMD64:
arch = Architecture.x64;
break;
case IMAGE_FILE_MACHINE_I386:
arch = Architecture.x86;
break;
case IMAGE_FILE_MACHINE_ARM64:
arch = Architecture.arm64;
break;
default:
return Architecture.Unknown;
}
return arch;
}
private static Architecture GetArchitecture(ref SYSTEM_INFO si)
{
switch (si.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_AMD64:
return Architecture.x64;
case PROCESSOR_ARCHITECTURE_ARM64:
return Architecture.arm64;
case PROCESSOR_ARCHITECTURE_INTEL:
return Architecture.x86;
default:
throw new PlatformNotSupportedException();
}
}
private const int PROCESSOR_ARCHITECTURE_AMD64 = 9;
private const int PROCESSOR_ARCHITECTURE_INTEL = 0;
private const int PROCESSOR_ARCHITECTURE_ARM64 = 12;
private const int IMAGE_FILE_MACHINE_ARM64 = 0xAA64;
private const int IMAGE_FILE_MACHINE_I386 = 0x14C;
private const int IMAGE_FILE_MACHINE_AMD64 = 0x8664;
[DllImport("kernel32")]
private static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
[DllImport("kernel32")]
private static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEM_INFO
{
public short wProcessorArchitecture;
public short wReserved;
public int dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public IntPtr lpMaximumApplicationAddress;
public IntPtr dwActiveProcessorMask;
public int dwNumberOfProcessors;
public int dwProcessorType;
public int dwAllocationGranularity;
public short wProcessorLevel;
public short wProcessorRevision;
}
This code supports x86, x64 and arm64 architectures and Windows XP. In modern versions of .NET you have built-in functions in the System.Runtime.InteropServices.RuntimeInformation namespace.