使用 C# 识别 CPU 架构类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/767613/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Identifying the CPU architecture type using C#
提问by Anirudh Goel
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!
我想检查用户运行的是哪种 CPU 架构,是 i386 或 X64 还是 AMD64。我想在 C# 中做到这一点。我知道我可以尝试 WMI 或注册表。除了这两个还有别的办法吗?我的项目面向 .NET 2.0!
采纳答案by Mehrdad Afshari
You could also try (only works if it's not manipulated):
你也可以尝试(只有在没有被操纵的情况下才有效):
System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
回答by Svish
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?
当然只是在开玩笑......我认为 WMI 是你会使用的。但也许还有其他方法?
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
如果您选择 WMI,那么 LinqToWmi 可能会有用。我试过一次,看起来很简单 =) -> http://www.codeplex.com/linq2wmi
回答by Anton Gogolev
Win32_ProcessorWMI Class will do the job. Use MgmtClassGen.exeto generate strongly-typed wrappers.
Win32_ProcessorWMI 类将完成这项工作。使用MgmtClassGen.exe生成强类型包装器。
回答by Erik Hellstr?m
回答by rama-jka toti
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.
我相信你应该避免像 WMI 和 LINQ 那样的严重膨胀……而且你最终必须在进行过程中获得更多信息,而膨胀的 apis 和框架都不能满足这些信息。
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).
只需调用一个调用并提取 CPUID 信息的 dll。C++/CLI 或 pinvoke 可以完成并获取您需要的有关供应商的所有信息。首先,您需要查看是否支持该指令(99% 的时间是支持的)。
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 )..
要快速启动并运行,请检查 intel 站点以获取 wincpuid 示例并从那里提取 cpuid.h 中的部分。只有 2 个供应商,一个在内存延迟方面表现良好,而另一个则没有(如本机代码与托管代码)。所以你会在其他架构等上遇到 Mono 问题(顺便说一句)。至于 x64,您已经知道它或者只是获得了 corflags(它已经存在并使用 .NET 发行版杀死了您的客户硬盘驱动器)。
(http://software.intel.com/en-us/articles/api-detects-ia-32-and-x64-platform-cpu-characteristics/)
(http://software.intel.com/en-us/articles/api-detects-ia-32-and-x64-platform-cpu-characteristics/)
回答by Brett
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.
如果您使用的是 64 位架构,您将有两个程序文件环境变量。如果您使用的是 x86,那么您将只有一个。
回答by dpminusa
This seems the simplest to me:
这对我来说似乎是最简单的:
System.Environment.Is64BitOperatingSystem
回答by Zak
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.
导致我在这里检查的是 32 位还是 64 位操作系统。评分最高的答案是查看Current process的设置。在没有找到答案后,我找到了以下设置。希望这对你有用。
bool is64 = System.Environment.Is64BitOperatingSystem
回答by Simon Mourier
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):
这是一段似乎有效的代码(基于 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;
}
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.
此代码支持 x86、x64 和 arm64 体系结构以及 Windows XP。在现代版本的 .NET 中,您在System.Runtime.InteropServices.RuntimeInformation 命名空间中有内置函数。
回答by metadings
Finally the shortest trick to resolve the platform/processor architecture for the current running CLR runtime in C# is:
最后,在 C# 中为当前运行的 CLR 运行时解析平台/处理器架构的最短技巧是:
PortableExecutableKinds peKind;
ImageFileMachine machine;
typeof(object).Module.GetPEKind(out peKind, out machine);
Here Module.GetPEKindreturns an ImageFileMachineenumeration, which exists since .NET v2:
这里Module.GetPEKind返回一个ImageFileMachine枚举,它从 .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):
为什么不使用new AssemblyName(fullName)
或typeof(object).Assembly.GetName()
?
那么HACK
在 ASP.NET MVC 源代码中有这个注释(自 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.
看他们为自己使用一些隐藏的技巧。可悲的是,AssemblyName
构造函数没有ProcessorArchitecture
适当地设置该字段,它只是None
用于任何新的 AssemblyName。
So for future readers, let me recommend you using that ugly GetPEKind with ImageFileMachine!
因此,对于未来的读者,让我建议您将丑陋的 GetPEKind 与 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.
- 这将返回当前运行的运行时架构,而不是底层系统架构!
也就是说,唯一的例外是 I386 运行时可能在 AMD64 系统上运行。 - 在 mono/ubuntu 14.04/AMD64 和 .NET/Win7/I386 上测试。