See the question and my original answer on StackOverflow

Here 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.