ユーザーが実行しているCPUアーキテクチャ(i386、X64、AMD64)を確認したいと思います。 C#でやりたいです。 WMIまたはレジストリを試すことができることはわかっています。これら2つ以外に他の方法はありますか?私のプロジェクトは.NET2.0を対象としています!
試すこともできます(操作されていない場合にのみ機能します):
System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
ここで私を導いたのは、32ビットと64ビットのOSをチェックすることです。最も評価の高い答えは、現在のプロセスの設定を確認することです。答えが見つからなかった後、私は次の設定を見つけました。これがあなたのために働くことを願っています。
bool is64 = System.Environment.Is64BitOperatingSystem
これは(P/Invokeに基づいて)機能しているように見えるコードの一部です:
public static ProcessorArchitecture GetProcessorArchitecture()
{
SYSTEM_INFO si = new SYSTEM_INFO();
GetNativeSystemInfo(ref si);
switch (si.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_AMD64:
return ProcessorArchitecture.AMD64;
case PROCESSOR_ARCHITECTURE_IA64:
return ProcessorArchitecture.IA64;
case PROCESSOR_ARCHITECTURE_INTEL:
return ProcessorArchitecture.X86;
default:
return ProcessorArchitecture.None; // that's weird :-)
}
}
と
[DllImport("kernel32.dll")]
private static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);
private const int PROCESSOR_ARCHITECTURE_AMD64 = 9;
private const int PROCESSOR_ARCHITECTURE_IA64 = 6;
private const int PROCESSOR_ARCHITECTURE_INTEL = 0;
[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;
}
このコードは既存のCLRの ProcessorArchitecture 列挙型を再利用し、.NET Framework2以降をサポートしていることに注意してください。
この質問は過去のものであることは知っていますが、2017年の時点で、現在のプロセスのアーキテクチャを知るための簡単な方法が.net標準にあります。
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture
返される値は、X86、X64、ARM、ARM64のいずれかであり、実行中のプロセスのアーキテクチャを示します。OSArchitecture
は、代わりに、インストールされているオペレーティングシステムのアーキテクチャを返します。
ドキュメントへのリンク(しかしかなり役に立たない...):
RuntimeInformation.ProcessArchitecture: https://docs.Microsoft.com/en-us/dotnet/api/system.runtime.interopservices.runtimeinformation.processarchitecture?view=netstandard-1.4
アーキテクチャの列挙: https://docs.Microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=netstandard-1.4
Win32_Processor WMIクラスがその仕事をします。 MgmtClassGen.exe を使用して、強く型付けされたラッパーを生成します。
最後に、C#で現在実行中のCLRランタイムのプラットフォーム/プロセッサアーキテクチャを解決するための最短のトリックは次のとおりです。
_PortableExecutableKinds peKind;
ImageFileMachine machine;
typeof(object).Module.GetPEKind(out peKind, out machine);
_
ここで Module.GetPEKind は ImageFileMachine 列挙を返します。これは.NETv2以降に存在します。
_public enum ImageFileMachine
{
I386 = 0x014C,
IA64 = 0x0200,
AMD64 = 0x8664,
ARM = 0x01C4 // new in .NET 4.5
}
_
new AssemblyName(fullName)
またはtypeof(object).Assembly.GetName()
を使用してみませんか?
ASP.NETMVCソースコードには次のHACK
コメントがあります(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);
}
_
彼らが彼ら自身のためにいくつかの隠されたトリックを使うのを見てください。残念ながら、AssemblyName
コンストラクターはProcessorArchitecture
フィールドを適切に設定せず、新しいAssemblyNameに対してはNone
にすぎません。
したがって、将来の読者のために、ImageFileMachineでその醜いGetPEKindを使用することをお勧めします!
ノート:
これはどう?
switch (typeof(string).Assembly.GetName().ProcessorArchitecture) {
case System.Reflection.ProcessorArchitecture.X86:
break;
case System.Reflection.ProcessorArchitecture.AMD64:
break;
case System.Reflection.ProcessorArchitecture.Arm:
break;
}
しかしながら case *.Arm:
はまだテストされていません。
知りたい理由によっては、IntPtr構造体のサイズを確認するのが最も簡単な方法であることがわかる場合があります。
多分 this CodeProjectの記事が役に立ちますか? System.Management名前空間のManagementObjectSearcherを使用して、ハードウェア情報を検索します。
これが私のやり方です:
オペレーティングシステムがLinuxの場合は、libc-syscall unameをピンボークします。ここで、プロセッサが[マシン]フィールドにあります。
OSが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
}
}
これは私には最も簡単なようです:
System.Environment.Is64BitOperatingSystem
あなたはおそらくユーザーに尋ねることができますか?
もちろん冗談です... WMIはそのために使用するものだと思います。しかし、他の方法もあるのでしょうか?
WMIを使用する場合は、LinqToWmiが役立つ可能性があります。一度試してみましたが、かなり簡単に見えました=)-> http://www.codeplex.com/linq2wmi
WMIやLINQのような大きな肥大化は避けるべきだと思います。最終的には、進行中に詳細情報を取得する必要がありますが、肥大化したAPIやフレームワークでは満足できません。
CPUID情報を呼び出して抽出するdllを呼び出すだけです。 C++/CLIまたはpinvokeが実行し、ベンダーで必要なすべての情報を取得します。まず、命令がサポートされているかどうかを確認する必要があります(99%の確率で)。
すばやく起動して実行するには、Intelサイトでwincpuidサンプルを確認し、そこからcpuid.hからピースを抽出します。ベンダーは2つしかなく、1つはメモリの待ち時間に優れており、もう1つはそうではありません(ネイティブコードとマネージコードのように)。そのため、他のアーキテクチャなどでMonoに問題が発生します(ところではありません)。 x64に関しては、あなたはすでにそれを知っているか、または単にcorflagsを取得します(すでにそこにあり、.NETディストリビューションで顧客のハードドライブを殺します)。
( http://software.intel.com/en-us/articles/api-detects-ia-32-and-x64-platform-cpu-characteristics/ )