Reputation: 13037
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
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