使用 C# 识别 CPU 架构类型

发布于 2024-07-18 04:41:57 字数 113 浏览 10 评论 0原文

我想检查用户运行的是哪个CPU架构,是吗 i386 或 X64 或 AMD64。 我想用 C# 来做。 我知道我可以尝试 WMI 或注册表。 除了这两种还有其他办法吗? 我的项目目标是.NET 2.0!

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 from these two?
My project targets .NET 2.0!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

安静 2024-07-25 04:41:57

我知道这个问题是过去的问题,但截至 2017 年,现在有一个简单的方法可以了解当前进程的体系结构,在 .net 标准中:

System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture

返回的值是 X86、X64、ARM、ARM64 之一,并给出它正在运行的进程的体系结构。OSArchitecture 返回已安装操作系统的体系结构。

文档链接(虽然没什么用......):

RuntimeInformation.ProcessArchitecture:
https://learn .microsoft.com/en-us/dotnet/api/system.runtime.interopservices.runtimeinformation.processarchitecture?view=netstandard-1.4

架构枚举:
https://learn.microsoft .com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=netstandard-1.4

I know that this question is from the past, but as of 2017, there is now a simple method to know the architecture of the current process, in .net standard :

System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture

The value returned is one of X86, X64, ARM, ARM64 and gives the architecture of the process it's running in. OSArchitecture returns the architecture of the installed operating system instead.

Links to the docs (pretty useless though...):

RuntimeInformation.ProcessArchitecture:
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.runtimeinformation.processarchitecture?view=netstandard-1.4

Architecture enumeration:
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=netstandard-1.4

晌融 2024-07-25 04:41:57

您也可以尝试(仅在不被操纵的情况下有效):

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

You could also try (only works if it's not manipulated):

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
ι不睡觉的鱼゛ 2024-07-25 04:41:57

让我来到这里的是检查 32 位与 64 位操作系统。 评分最高的答案是查看当前进程的设置。 在找不到答案后,我找到了以下设置。 希望这对你有用。

bool is64 = System.Environment.Is64BitOperatingSystem

What led me here is checking for a 32 vs 64 bit OS. the highest rated answer is looking at the setting for the Current process. After not finding an answer I found the following setting. Hope this works for you.

bool is64 = System.Environment.Is64BitOperatingSystem
单调的奢华 2024-07-25 04:41:57

这是一段似乎可以工作的代码(基于 P/Invoke); 它允许确定 CPU/机器架构、当前进程架构以及给定的二进制文件架构(如何编译):

    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;
    }

此代码支持 x86、x64 和 arm64 架构以及 Windows XP。 在现代版本的 .NET 中,您在 System.Runtime.InteropServices.RuntimeInformation 命名空间

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.

執念 2024-07-25 04:41:57

Win32_Processor WMI 类将完成这项工作。 使用 MgmtClassGen.exe 生成强类型包装器。

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

慕烟庭风 2024-07-25 04:41:57

最后,解决 C# 中当前运行的 CLR 运行时的平台/处理器体系结构的最短技巧是:

PortableExecutableKinds peKind;
ImageFileMachine machine;
typeof(object).Module.GetPEKind(out peKind, out machine);

这里 Module.GetPEKind 返回 ImageFileMachine 枚举,自 .NET v2 以来就存在:

public enum ImageFileMachine
{
    I386    = 0x014C,
    IA64    = 0x0200,
    AMD64   = 0x8664,
    ARM     = 0x01C4    // new in .NET 4.5
}

为什么不使用 new AssemblyName(fullName) 或 <代码>typeof(object).Assembly.GetName()?
ASP.NET MVC 源代码(自 1.0 起)中有这样的 HACK 注释:

private static string GetMvcVersionString() {
    // DevDiv 216459:
    // This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in
    // medium trust. However, Assembly.FullName *is* accessible in medium trust.
    return new AssemblyName(typeof(MvcHttpHandler).Assembly.FullName).Version.ToString(2);
}

看看他们为自己使用了一些隐藏的技巧。 遗憾的是,AssemblyName 构造函数没有正确设置 ProcessorArchitecture 字段,对于任何新的 AssemblyName,它只是 None

因此,对于未来的读者,我建议您使用丑陋的 GetPEKind 和 ImageFileMachine!

注意:

  • 这将返回当前正在运行的运行时架构,而不是底层系统架构!
    也就是说,唯一的例外是 I386 运行时可以在 AMD64 系统上运行。
  • 在 mono/ubuntu 14.04/AMD64 和 .NET/Win7/I386 上测试。

Finally the shortest trick to resolve the platform/processor architecture for the current running CLR runtime in C# is:

PortableExecutableKinds peKind;
ImageFileMachine machine;
typeof(object).Module.GetPEKind(out peKind, out machine);

Here Module.GetPEKind returns an ImageFileMachine enumeration, which exists since .NET v2:

public enum ImageFileMachine
{
    I386    = 0x014C,
    IA64    = 0x0200,
    AMD64   = 0x8664,
    ARM     = 0x01C4    // new in .NET 4.5
}

Why not use new AssemblyName(fullName) or typeof(object).Assembly.GetName()?
Well there is this HACK comment in ASP.NET MVC source code (since 1.0):

private static string GetMvcVersionString() {
    // DevDiv 216459:
    // This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in
    // medium trust. However, Assembly.FullName *is* accessible in medium trust.
    return new AssemblyName(typeof(MvcHttpHandler).Assembly.FullName).Version.ToString(2);
}

See they use some hidden tricks for themselves. Sadly, the AssemblyName constructor doesn't set the ProcessorArchitecture field appropriately, it's just None for whatever new AssemblyName.

So for future readers, let me recommend you using that ugly GetPEKind with ImageFileMachine!

Notes:

  • This returns the current running runtime architecture, not the underlying system architecture!
    That said, the only exception is that an I386 runtime may run on an AMD64 system.
  • Tested on mono/ubuntu 14.04/AMD64 and .NET/Win7/I386.
站稳脚跟 2024-07-25 04:41:57

这个怎么样?

switch (typeof(string).Assembly.GetName().ProcessorArchitecture) {
    case System.Reflection.ProcessorArchitecture.X86:
        // '$(Platform)' == 'x86'
        break;
    case System.Reflection.ProcessorArchitecture.Amd64:
        // '$(Platform)' == 'x64'
        break;
    case System.Reflection.ProcessorArchitecture.MSIL:
        // MacBook Pro with M1 Pro (from comment)
        // Linux aarch64 (net60; AWS Graviton2)
        // Windows 11 Pro (net60; Arm64-based Azure VM)
        break;
    case System.Reflection.ProcessorArchitecture.None:
        // ASP.NET Core Blazor WebAssembly (net60)
        break;
    case System.Reflection.ProcessorArchitecture.Arm:
        // Unknown
        break;
}

但是 case *.Arm: 尚未测试。

How about this?

switch (typeof(string).Assembly.GetName().ProcessorArchitecture) {
    case System.Reflection.ProcessorArchitecture.X86:
        // '$(Platform)' == 'x86'
        break;
    case System.Reflection.ProcessorArchitecture.Amd64:
        // '$(Platform)' == 'x64'
        break;
    case System.Reflection.ProcessorArchitecture.MSIL:
        // MacBook Pro with M1 Pro (from comment)
        // Linux aarch64 (net60; AWS Graviton2)
        // Windows 11 Pro (net60; Arm64-based Azure VM)
        break;
    case System.Reflection.ProcessorArchitecture.None:
        // ASP.NET Core Blazor WebAssembly (net60)
        break;
    case System.Reflection.ProcessorArchitecture.Arm:
        // Unknown
        break;
}

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

冬天的雪花 2024-07-25 04:41:57

也许这篇 CodeProject 文章会有所帮助? 它使用 System.Management 命名空间中的 ManagementObjectSearcher 来搜索硬件信息。

Maybe this CodeProject article could help? It uses the ManagementObjectSearcher in the System.Management namespace to search for hardware info.

对不⑦ 2024-07-25 04:41:57

根据您想知道的原因,您可能会发现检查 IntPtr 结构的大小是最简单的方法。

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

对不⑦ 2024-07-25 04:41:57

你也许可以问问用户?

当然只是开玩笑...我认为 WMI 就是您所使用的。 但也许还有其他方法呢?

如果您选择 WMI,那么 LinqToWmi 可能会有用。 我尝试过一次,看起来非常简单 =) -> http://www.codeplex.com/linq2wmi

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

月竹挽风 2024-07-25 04:41:57

这对我来说似乎是最简单的:

System.Environment.Is64BitOperatingSystem

This seems the simplest to me:

System.Environment.Is64BitOperatingSystem
沐歌 2024-07-25 04:41:57

这是我的方法:

如果操作系统是 Linux,则调用 libc-syscall uname,您将在 Machine 字段中看到处理器。

如果操作系统是Windows,检查System.IntPtr.Size * 8 = 64,则它是64位。
如果不是 64 位,则检查 IsWow64Process 是否存在,如果存在,并且进程是 Wow64,则它是 x86-64,否则它是 x86-32。

这个是可靠的。
检查处理器架构环境变量则不然。

代码:

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


    }


}

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


    }


}
无可置疑 2024-07-25 04:41:57

我使用了这个:Environment.Is64BitOperatingSystem

例如:Environment.Is64BitOperatingSystem ? "win-x64" : "win-x86"

它适用于 .NET Framework 4.0、4.5、4.5.1、4.5.2、4.6、4.6.1、4.6.2、4.7、4.7。 1、4.7.2、4.8、4.8.1

I used this: Environment.Is64BitOperatingSystem

for example: Environment.Is64BitOperatingSystem ? "win-x64" : "win-x86"

it's applied to .NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1

你如我软肋 2024-07-25 04:41:57

我相信你应该避免像 WMI 和 LINQ 这样的臃肿的东西..并且你最终必须这样做,以便在你进行的过程中获得更多的信息,而臃肿的 API 和框架无法满足这些信息。

只需调用一个 dll 来调用并提取 CPUID 信息。 C++/CLI 或 pinvoke 就可以,并获取您需要的有关供应商的所有信息。 首先您需要查看该指令是否受支持(99% 的情况下是支持的)。

要快速启动和运行,请检查 intel 站点上的 wincpuid 示例,并从那里提取 cpuid.h 中的部分。 只有 2 家供应商,其中一家在内存延迟方面表现出色,而另一家则不然(例如本机代码与托管代码)。 所以你会在其他架构等上遇到 Mono 的问题(顺便说一句谁没有)。 至于 x64,您已经知道它,或者只是获取 corflags(它已经存在并通过 .NET 发行版杀死您的客户硬盘驱动器)..

(http://software.intel.com/en-us/articles/api-detects-ia-32 -和-x64-平台-cpu-特性/)

I believe you should avoid heavy bloat like WMI and LINQ.. and you'll have to eventually, to get more info as you go along, none of which are satisfied by bloated apis and frameworks.

Just invoke a dll that calls and extracts CPUID info. C++/CLI or pinvoke would do and get all the info you need on the vendor. First you need to see whether the instruction is supported (99% of the time it is).

To get quickly up and running is to check the intel site for wincpuid sample and extract the piece from cpuid.h from there. There are only 2 vendors and one is good with memory latency and the other one isn't (like native vs managed code). So you'll have issues with Mono on other architectures etc (who doesn't btw). As for x64 you already know it or just get the corflags (its there already and killing your customer hard drive with .NET distribution )..

(http://software.intel.com/en-us/articles/api-detects-ia-32-and-x64-platform-cpu-characteristics/)

绾颜 2024-07-25 04:41:57

这就是我所做的:

public static bool Isx86()
{
    return (Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%").Length == 0);
}

如果您使用 64 位体系结构,您将有两个程序文件环境变量。 如果您使用的是 x86,则只有一个。

Here's what I did:

public static bool Isx86()
{
    return (Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%").Length == 0);
}

If you're on 64 bit architecture you'll have two program file env variables. If you're on x86, you'll only have the one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文