Identifying the CPU architecture type using C#

前端 未结 14 2108
心在旅途
心在旅途 2020-12-01 17:52

I want to check which CPU architecture is the user running, is it i386 or X64 or AMD64. I want to do it in C#. I know i can try WMI or Registry. Is there any other way apart

相关标签:
14条回答
  • 2020-12-01 18:30

    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.

    0 讨论(0)
  • 2020-12-01 18:30

    How about this?

    switch (typeof(string).Assembly.GetName().ProcessorArchitecture) {
        case System.Reflection.ProcessorArchitecture.X86:
            break;
        case System.Reflection.ProcessorArchitecture.Amd64:
            break;
        case System.Reflection.ProcessorArchitecture.Arm:
            break;
    }
    

    However case *.Arm: isn't tested yet.

    0 讨论(0)
  • 2020-12-01 18:32

    Win32_Processor WMI Class will do the job. Use MgmtClassGen.exe to generate strongly-typed wrappers.

    0 讨论(0)
  • 2020-12-01 18:34

    Depending on why you want to know, you might find that checking the size of the IntPtr structure is the easiest way.

    0 讨论(0)
  • 2020-12-01 18:36

    You could ask the user perhaps?

    Just kidding of course... I think WMI is what you would use for that. But maybe there is some other way as well?

    If you go for WMI then LinqToWmi could be of use. I tried it out once, and it seemed pretty straight forward =) -> http://www.codeplex.com/linq2wmi

    0 讨论(0)
  • 2020-12-01 18:37

    Here is my way:

    If the operating system is Linux, pinvoke the libc-syscall uname, where you will have the processor in the Machine-field.

    If the OS is Windows, check if System.IntPtr.Size * 8 = 64, then it's 64 bit. If it isn't 64-Bit, you check if IsWow64Process exists, and if it exists, and the process is Wow64, then it's x86-64, else it's x86-32.

    This one is reliable.
    Checking the processor-architecture environment variables is not.

    Code:

    namespace RamMonitorPrototype
    {
    
    
        // https://stackoverflow.com/a/55202696/155077
        //[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        //unsafe internal struct Utsname_internal
        //{
        //    public fixed byte sysname[65];
        //    public fixed byte nodename[65];
        //    public fixed byte release[65];
        //    public fixed byte version[65];
        //    public fixed byte machine[65];
        //    public fixed byte domainname[65];
        //}
    
    
        public class Utsname
        {
            public string SysName; // char[65]
            public string NodeName; // char[65]
            public string Release; // char[65]
            public string Version; // char[65]
            public string Machine; // char[65]
            public string DomainName; // char[65]
    
            public void Print()
            {
                System.Console.Write("SysName:\t");
                System.Console.WriteLine(this.SysName); // Linux 
    
                System.Console.Write("NodeName:\t");
                System.Console.WriteLine(this.NodeName); // System.Environment.MachineName
    
                System.Console.Write("Release:\t");
                System.Console.WriteLine(this.Release); // Kernel-version
    
                System.Console.Write("Version:\t");
                System.Console.WriteLine(this.Version); // #40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019
    
                System.Console.Write("Machine:\t");
                System.Console.WriteLine(this.Machine); // x86_64
    
                System.Console.Write("DomainName:\t");
                System.Console.WriteLine(this.DomainName); // (none)
            }
    
    
        }
    
    
        // https://github.com/microsoft/referencesource/blob/master/System/compmod/microsoft/win32/UnsafeNativeMethods.cs
        // https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Environment.Windows.cs
        public class DetermineOsBitness
        {
            private const string Kernel32 = "kernel32.dll";
    
    
    
            [System.Runtime.InteropServices.DllImport("libc", EntryPoint = "uname", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
            private static extern int uname_syscall(System.IntPtr buf);
    
            // https://github.com/jpobst/Pinta/blob/master/Pinta.Core/Managers/SystemManager.cs
            public static Utsname Uname()
            {
                Utsname uts = null;
                System.IntPtr buf = System.IntPtr.Zero;
    
                buf = System.Runtime.InteropServices.Marshal.AllocHGlobal(8192);
                // This is a hacktastic way of getting sysname from uname ()
                if (uname_syscall(buf) == 0)
                {
                    uts = new Utsname();
                    uts.SysName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(buf);
    
                    long bufVal = buf.ToInt64();
                    uts.NodeName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new System.IntPtr(bufVal + 1 * 65));
                    uts.Release = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new System.IntPtr(bufVal + 2 * 65));
                    uts.Version = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new System.IntPtr(bufVal + 3 * 65));
                    uts.Machine = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new System.IntPtr(bufVal + 4 * 65));
                    uts.DomainName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new System.IntPtr(bufVal + 5 * 65));
    
                    if (buf != System.IntPtr.Zero)
                        System.Runtime.InteropServices.Marshal.FreeHGlobal(buf);
                } // End if (uname_syscall(buf) == 0) 
    
                return uts;
            } // End Function Uname
    
    
    
            [System.Runtime.InteropServices.DllImport(Kernel32, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false)]
            [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.Machine)]
            private static extern System.IntPtr GetModuleHandle(string modName);
    
    
            [System.Runtime.InteropServices.DllImport(Kernel32, CharSet = System.Runtime.InteropServices.CharSet.Ansi, BestFitMapping = false, SetLastError = true, ExactSpelling = true)]
            [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.None)]
            private static extern System.IntPtr GetProcAddress(System.IntPtr hModule, string methodName);
    
    
            [System.Runtime.InteropServices.DllImport(Kernel32, SetLastError = true, CallingConvention = System.Runtime.InteropServices.CallingConvention.Winapi)]
            [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
            private static extern bool IsWow64Process(
                 [System.Runtime.InteropServices.In] Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid hProcess,
                 [System.Runtime.InteropServices.Out, System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] out bool wow64Process
            );
    
    
            [System.Security.SecurityCritical]
            private static bool DoesWin32MethodExist(string moduleName, string methodName)
            {
                System.IntPtr hModule = GetModuleHandle(moduleName);
    
                if (hModule == System.IntPtr.Zero)
                {
                    System.Diagnostics.Debug.Assert(hModule != System.IntPtr.Zero, "GetModuleHandle failed.  Dll isn't loaded?");
                    return false;
                }
    
                System.IntPtr functionPointer = GetProcAddress(hModule, methodName);
                return (functionPointer != System.IntPtr.Zero);
            }
    
            public static bool Is64BitOperatingSystem()
            {
                if (System.IntPtr.Size * 8 == 64)
                    return true;
    
                if (!DoesWin32MethodExist(Kernel32, "IsWow64Process"))
                    return false;
    
                bool isWow64;
    
                using(Microsoft.Win32.SafeHandles.SafeWaitHandle safeHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(System.Diagnostics.Process.GetCurrentProcess().Handle, true))
                {
                    IsWow64Process(safeHandle, out isWow64);
                }
                return isWow64;
            }
    
            // This doesn't work reliably
            public static string GetProcessorArchitecture()
            {
                string strProcessorArchitecture = null;
    
                try
                {
                    strProcessorArchitecture = System.Convert.ToString(System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"));
    
                    switch (typeof(string).Assembly.GetName().ProcessorArchitecture)
                    {
                        case System.Reflection.ProcessorArchitecture.X86:
                            strProcessorArchitecture = "x86";
                            break;
                        case System.Reflection.ProcessorArchitecture.Amd64:
                            strProcessorArchitecture = "x86";
                            break;
                        case System.Reflection.ProcessorArchitecture.Arm:
                            strProcessorArchitecture = "ARM";
                            break;
                    }
    
                    bool is64bit = !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"));
    
                    if (is64bit)
                        strProcessorArchitecture += "-64";
                    else
                        strProcessorArchitecture += "-32";
                }
                catch (System.Exception ex)
                {
                    strProcessorArchitecture = ex.Message;
                }
    
                return strProcessorArchitecture;
            } // End Function GetProcessorArchitecture
    
    
        }
    
    
    }
    
    0 讨论(0)
提交回复
热议问题