Find Machine Types in .NET

.Net Tutorials

A frequent question that comes up on developer forums like CodeGuru forums is: “How do I find the machine types in .NET?”. I can not believe I have not covered this topic before as most of my articles these days are more informative than instructional. To fix this, I will be answering this very question in today’s .NET programming tutorial.

Let’s get started!

First, what are the machine types that I am talking about? These are usually laptops or machines that are either 64 bit or 32 bit. Before we go forward, we need to understand a concept known as Portable Executables, or PE for short.

What are Portable Executables (PE)?

The Portable Executable format is a file format for all executables, DLLs and object code used in 32-bit and 64-bit operating systems. This format is a data structure that contains all the necessary information for the Operating System loader to manage the executable code.

The PE format is mostly used for EXE (executables – physical program files), DLL (dynamic linked libraries), SYS (system device drivers), MUI (Multilingual User Interface) and other file types.

According to Wikipedia:

“On Windows NT operating systems, PE currently supports the x86-32, x86-64 (AMD64/Intel 64), IA-64, ARM and ARM64 instruction set architectures (ISAs). Prior to Windows 2000, Windows NT (and thus PE) supported the MIPS, Alpha, and PowerPC ISAs. Because PE is used on Windows CE, it continues to support several variants of the MIPS, ARM (including Thumb), and SuperH ISAs.”

Finding Machine Types in .NET with PE Headers

To find the machine type in .NET, we can use PE headers. To do so, follow these steps:

  • Create a project in Visual Studio 2022
  • Create a new class and name it MachineTypes
  • Enter the following into this class:
namespace Machine_Type
{
    public class Machines
    {
        private static MachineType GetDllMachineType(string dllPath)
        {
            FileStream fsStream = new FileStream(dllPath, FileMode.Open, FileAccess.Read);
            BinaryReader brReader = new BinaryReader(fsStream);

            fsStream.Seek(0x3c, SeekOrigin.Begin);
            Int32 peOffset = brReader.ReadInt32();
            fsStream.Seek(peOffset, SeekOrigin.Begin);
            UInt32 peHead = brReader.ReadUInt32();

            if (peHead != 0x00004550) 
                throw new Exception("Can't find PE header");

            MachineType = (MachineType)brReader.ReadUInt16();

            brReader.Close();
            fsStream.Close();
            return machineType;
        }

        public static bool? DllIs64Bit(string dllPath)
        {
            switch (GetDllMachineType(dllPath))
            {
                case MachineType.IMAGE_FILE_MACHINE_AMD64:
                case MachineType.IMAGE_FILE_MACHINE_IA64:
                    return true;
                case MachineType.IMAGE_FILE_MACHINE_I386:
                    return false;
                default:
                    return null;
            }
        }

        public enum MachineType : ushort
        {
            IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
            IMAGE_FILE_MACHINE_AM33 = 0x1d3,
            IMAGE_FILE_MACHINE_AMD64 = 0x8664,
            IMAGE_FILE_MACHINE_ARM = 0x1c0,
            IMAGE_FILE_MACHINE_EBC = 0xebc,
            IMAGE_FILE_MACHINE_I386 = 0x14c,
            IMAGE_FILE_MACHINE_IA64 = 0x200,
            IMAGE_FILE_MACHINE_M32R = 0x9041,
            IMAGE_FILE_MACHINE_MIPS16 = 0x266,
            IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
            IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
            IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
            IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
            IMAGE_FILE_MACHINE_R4000 = 0x166,
            IMAGE_FILE_MACHINE_SH3 = 0x1a2,
            IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
            IMAGE_FILE_MACHINE_SH4 = 0x1a6,
            IMAGE_FILE_MACHINE_SH5 = 0x1a8,
            IMAGE_FILE_MACHINE_THUMB = 0x1c2,
            IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
        }
    }
}

A note on IMAGE_FILE Headers: the IMAGE_NT_HEADERS structure is the primary location where specifics of the Portable Executables file are stored. There are two versions of the IMAGE_NT_HEADER structure – 32-bit and 64-bit executables.

Read more .NET programming and software development tutorials.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Must Read