Vegard Larsen
Vegard Larsen

Reputation: 13037

How to detect if Windows supports running x64 processes?

Starting in December 2020, Windows supports x64 emulation on ARM64 devices. How can a program determine if the current version of Windows supports running x64 applications?

Prior to x64 emulation on ARM64, we could use RuntimeInformation.OSArchitecture == Architecture.X64 for this.

Upvotes: 1

Views: 375

Answers (1)

Daniel Paoliello
Daniel Paoliello

Reputation: 306

You can use GetMachineTypeAttributes (https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getmachinetypeattributes) to check if Windows supports running x64 code.

For example:

using System;
using System.Runtime.InteropServices;

public class Program
{
    [Flags]
    enum MachineAttributes
    {
        None = 0,
        UserEnabled = 0x00000001,
        KernelEnabled = 0x00000002,
        Wow64Container = 0x00000004,
    }

    [DllImport("kernel32.dll", PreserveSig = false)]
    static extern MachineAttributes GetMachineTypeAttributes(ushort WowGuestMachine);
    const ushort IMAGE_FILE_MACHINE_AMD64 = 0x8664;
    const ushort IMAGE_FILE_MACHINE_I386 = 0x014c;
    const ushort IMAGE_FILE_MACHINE_ARM64 = 0xAA64;

    public static void Main()
    {
        var x64Support = GetMachineTypeAttributes(IMAGE_FILE_MACHINE_AMD64);
        Console.WriteLine("x64 support: {0}", x64Support);
        var x86Support = GetMachineTypeAttributes(IMAGE_FILE_MACHINE_I386);
        Console.WriteLine("x86 support: {0}", x86Support);
        var arm64Support = GetMachineTypeAttributes(IMAGE_FILE_MACHINE_ARM64);
        Console.WriteLine("Arm64 support: {0}", arm64Support);

    }
}

Running this on an x64 device produces:

x64 support: UserEnabled, KernelEnabled
x86 support: UserEnabled, Wow64Container
Arm64 support: None

And on an Arm64 Win11 device produces:

x64 support: UserEnabled
x86 support: UserEnabled, Wow64Container
Arm64 support: UserEnabled, KernelEnabled

So to detect if x64 code can be run, check if the returned value is not MachineAttributes.None:

public static bool SupportsX64()
{
    return GetMachineTypeAttributes(IMAGE_FILE_MACHINE_AMD64) != MachineAttributes.None;
}

Updated

Looks like GetMachineTypeAttributes was added in Win11, so if attempting to P/Invoke it throws EntryPointNotFoundException then you know that you're running on pre-Win11 and can use your older detection logic:

public static bool SupportsX64()
{
    try
    {
        // Win11+: Ask the OS if we can run AMD64 code.
        return GetMachineTypeAttributes(IMAGE_FILE_MACHINE_AMD64) != MachineAttributes.None;
    }
    catch (EntryPointNotFoundException)
    {
        // Pre-Win11: Only x64 machines can run x64 code.
        return RuntimeInformation.OSArchitecture == Architecture.X64;
    }
}

Upvotes: 2

Related Questions