You are about to copy a program to an older machine, load a plug-in DLL into an application, or work out why Windows says a file is not a valid Win32 application. The first question is always the same: is it 32-bit or 64-bit? A 64-bit program will not start on 32-bit Windows, and a process can only load DLLs of its own bitness.
You do not need to run the file to find out. Every Windows program and DLL records the processor it was built for in its header, a few hundred bytes from the start. This article shows where that is, the quickest ways to read it, and the cases where the header does not tell the whole story.
Checked on Windows 10 Pro 22H2 in November 2026.
Windows programs, DLLs and drivers use the Portable Executable (PE) format. Every one starts with the two letters MZ. At offset 0x3C is a 4-byte number giving the position of the PE header, which starts with PE followed by two zero bytes. The next two bytes are the machine type:
The PE header is not at a fixed place. It depends on the size of the old MS-DOS stub in front of it, so always follow the pointer at 0x3C rather than looking at a fixed offset. A little further on, the optional header starts with 010B for a 32-bit layout (PE32) or 020B for a 64-bit one (PE32+).
This reads the first 4 KB of a file and prints the machine type. It works in Windows PowerShell 5.1, which every copy of Windows 10 and 11 has:
function Get-Machine ($Path) {
$f = [IO.File]::OpenRead($Path); $b = New-Object byte[] 4096
[void]$f.Read($b, 0, 4096); $f.Close()
$pe = [BitConverter]::ToInt32($b, 0x3C)
'{0:X4}' -f [BitConverter]::ToUInt16($b, $pe + 4) }
Get-Machine C:\Windows\System32\notepad.exe
On a 64-bit copy of Windows that prints 8664; the same command on C:\Windows\SysWOW64\notepad.exe prints 014C. Run it in a 64-bit PowerShell window, for the reason given under the traps below.
Task Manager's Platform column (Details tab, right-click a column heading, Select columns) also shows 32-bit or 64-bit, but only for programs that are already running, and never for a DLL.
A .NET program contains intermediate code that is compiled when it runs, so it can run as 32-bit or 64-bit whatever its header says. Most .NET programs built as AnyCPU have a 32-bit (014C, PE32) header and still run as 64-bit on 64-bit Windows. That is why a header check, and some tools, report them as 32-bit.
The real answer is in flags in the .NET header, which corflags shows:
The .NET Framework folder has examples of each: in C:\Windows\Microsoft.NET\Framework\v4.0.30319, AddInProcess32.exe is 32-bit only while AddInProcess.exe is AnyCPU, even though both headers say 014C.
Windows on Arm adds three more answers. Native Arm programs are AA64. ARM64EC programs are Arm code built to sit alongside x64 code in one process, and their header says 8664. ARM64X files hold both Arm and Arm64EC code, and their header says AA64. Both kinds are marked by an extra table in the file's load configuration, so a plain machine-type check cannot tell them apart from ordinary x64 and Arm files.
System32 is not System32. On 64-bit Windows, a 32-bit program that opens C:\Windows\System32\anything is silently given C:\Windows\SysWOW64\anything instead. This is the WOW64 file system redirector, and it is how 32-bit programs keep working. The result is that a 32-bit checker reports a 64-bit system file as 32-bit, because it was never shown the file you asked about. Use a 64-bit tool, or a 32-bit one that turns redirection off while it opens the file.
The version lie. A program without a manifest that declares Windows 10 support is told that Windows system files are version 6.2, which is Windows 8. Asking for the version of notepad.exe from such a program gives 6.2.19041.x, while the file itself says 10.0.19041.x. Windows also merges in strings from the separate language (.mui) file, so a field like the original file name can come back as notepad.exe.mui.
Exe Info is our free Windows tool that answers all of this in one window, without running the file:
It comes as a 64-bit and a 32-bit build. The 32-bit build turns off redirection while it reads a file, so it reports System32 files correctly, and it reads version information straight from the file, so it is not given the version lie. Files can be dragged onto it, opened from the Explorer right-click menu, and the whole report copied or saved as text.
Please chip in if helpful