Как определить 64-разрядную платформу Windows with.NET?
в Приложении.NET 2.0 C# я использую следующий код для обнаружения платформы операционной системы:
string os_platform = System.Environment.OSVersion.Platform.ToString();
Это возвращает "Win32NT". Проблема в том, что он возвращает "Win32NT" даже при работе на Windows Vista 64-бит.
есть ли другой способ узнать правильную платформу (32 или 64 бит)?
обратите внимание, что он также должен обнаружить 64 бит при запуске в качестве 32-разрядного приложения на 64-разрядной Windows.
29 ответов:
IntPtr.Размер не вернет правильное значение, если он работает в 32-разрядной .NET Framework 2.0 на 64-разрядной Windows (он вернет 32-разрядную версию).
как описывает Раймонд Чен из Microsoft, вы должны сначала проверить, работает ли 64-разрядный процесс (я думаю, что в .NET вы можете сделать это, проверив IntPtr.Размер), и если вы работаете в 32-разрядном процессе, вам все равно нужно вызвать функцию win API IsWow64Process. Если это возвращает true, вы работаете в 32-разрядный процесс на 64-разрядной Окна.
Рэймонд Чен из Microsoft: как программно определить, работаете ли вы на 64-разрядной Windows
мое решение:
static bool is64BitProcess = (IntPtr.Size == 8); static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64(); [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWow64Process( [In] IntPtr hProcess, [Out] out bool wow64Process ); public static bool InternalCheckIsWow64() { if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6) { using (Process p = Process.GetCurrentProcess()) { bool retVal; if (!IsWow64Process(p.Handle, out retVal)) { return false; } return retVal; } } else { return false; } }
.NET 4 имеет два новых свойства в классе среды,Is64BitProcess и Is64BitOperatingSystem. Интересно, что если вы используете Reflector, вы можете видеть, что они реализованы по-разному в 32-разрядных и 64-разрядных версиях mscorlib. 32-разрядная версия возвращает false для Is64BitProcess и вызывает IsWow64Process через P / Invoke для Is64BitOperatingSystem. 64-разрядная версия просто возвращает true для обоих.
Если вы используете.NET Framework 4.0, это просто:
Environment.Is64BitOperatingSystem
См Environment. Is64BitOperatingSystem Свойство (MSDN).
Это просто реализация того, что предложил выше Бруно Лопес, но работает на Win2k + все пакеты обновления WinXP. Просто подумал, что я отправлю его, чтобы другие люди не свернули его вручную. (написал бы в качестве комментария, но я новый пользователь!)
[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr LoadLibrary(string libraryName); [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName); private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process); public static bool IsOS64Bit() { if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor())) { return true; } else { return false; } } private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate() { IntPtr handle = LoadLibrary("kernel32"); if ( handle != IntPtr.Zero) { IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process"); if (fnPtr != IntPtr.Zero) { return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate)); } } return null; } private static bool Is32BitProcessOn64BitProcessor() { IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate(); if (fnDelegate == null) { return false; } bool isWow64; bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64); if (retVal == false) { return false; } return isWow64; }
полный ответ таков (взят из ответа Стефана-mg, ripper234 и BobbyShaftoe):
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo); private bool Is64Bit() { if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor())) { return true; } else { return false; } } private bool Is32BitProcessOn64BitProcessor() { bool retVal; IsWow64Process(Process.GetCurrentProcess().Handle, out retVal); return retVal; }
сначала проверьте, если вы находитесь в 64-разрядном процессе. Если это не так, проверьте, является ли 32-разрядный процесс Wow64Process.
Microsoft поместила пример кода для этого:
http://1code.codeplex.com/SourceControl/changeset/view/39074#842775
это выглядит так:
/// <summary> /// The function determines whether the current operating system is a /// 64-bit operating system. /// </summary> /// <returns> /// The function returns true if the operating system is 64-bit; /// otherwise, it returns false. /// </returns> public static bool Is64BitOperatingSystem() { if (IntPtr.Size == 8) // 64-bit programs run only on Win64 { return true; } else // 32-bit programs run on both 32-bit and 64-bit Windows { // Detect whether the current process is a 32-bit process // running on a 64-bit system. bool flag; return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(GetCurrentProcess(), out flag)) && flag); } } /// <summary> /// The function determins whether a method exists in the export /// table of a certain module. /// </summary> /// <param name="moduleName">The name of the module</param> /// <param name="methodName">The name of the method</param> /// <returns> /// The function returns true if the method specified by methodName /// exists in the export table of the module specified by moduleName. /// </returns> static bool DoesWin32MethodExist(string moduleName, string methodName) { IntPtr moduleHandle = GetModuleHandle(moduleName); if (moduleHandle == IntPtr.Zero) { return false; } return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero); } [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)]string procName); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
также доступна версия WMI (для тестирования удаленных машин).
вы также можете проверить для
PROCESSOR_ARCHITECTURE
переменные среды.Он либо не существует, либо установлен на "x86" в 32-разрядной Windows.
private int GetOSArchitecture() { string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64); }
из блога Chriz Yuen
C# .Net 4.0 представил два новых свойства среды Среды.Is64BitOperatingSystem; Environment. Is64BitProcess;
пожалуйста, будьте осторожны, когда вы используете эти оба свойства. Тест на Windows 7 64bits Machine
//Workspace: Target Platform x86 Environment.Is64BitOperatingSystem True Environment.Is64BitProcess False //Workspace: Target Platform x64 Environment.Is64BitOperatingSystem True Environment.Is64BitProcess True //Workspace: Target Platform Any Environment.Is64BitOperatingSystem True Environment.Is64BitProcess True
@foobar: вы правы, это слишком просто ;)
в 99% случаев разработчики со слабым опытом системного администратора в конечном итоге не могут понять, что Microsoft всегда предоставляла кому-либо возможность перечислять Windows.
системные администраторы всегда будут писать лучше и проще код, когда дело доходит до такой точки.
тем не менее, одна вещь, чтобы отметить, конфигурация сборки должна быть AnyCPU чтобы эта переменная среды возвращалась правильные значения в правильных системах:
System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
это вернет "X86 "на 32-разрядной Windows, и" AMD64 " на 64-разрядной Windows.
быстрый способ:
if(IntPtr.Size == 8) { // 64 bit machine } else if(IntPtr.Size == 4) { // 32 bit machine }
Примечание: это очень прямой.
используйте эти две переменные среды (псевдокод):
if (PROCESSOR_ARCHITECTURE = x86 && isDefined(PROCESSOR_ARCHITEW6432) && PROCESSOR_ARCHITEW6432 = AMD64) { //64 bit OS } else if (PROCESSOR_ARCHITECTURE = AMD64) { //64 bit OS } else if (PROCESSOR_ARCHITECTURE = x86) { //32 bit OS }
см. сообщение в блоге методические указания: определить процесс разрядности.
используя dotPeek помогает увидеть, как платформа на самом деле это делает. Имея это в виду, вот что я придумал:
public static class EnvironmentHelper { [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll")] static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32")] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll")] static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process); public static bool Is64BitOperatingSystem() { // Check if this process is natively an x64 process. If it is, it will only run on x64 environments, thus, the environment must be x64. if (IntPtr.Size == 8) return true; // Check if this process is an x86 process running on an x64 environment. IntPtr moduleHandle = GetModuleHandle("kernel32"); if (moduleHandle != IntPtr.Zero) { IntPtr processAddress = GetProcAddress(moduleHandle, "IsWow64Process"); if (processAddress != IntPtr.Zero) { bool result; if (IsWow64Process(GetCurrentProcess(), out result) && result) return true; } } // The environment must be an x86 environment. return false; } }
пример использования:
EnvironmentHelper.Is64BitOperatingSystem();
Мне нужно это сделать, но мне также нужно быть в состоянии как администратор сделать это удаленно, в любом случае это, кажется, работает довольно хорошо для меня:
public static bool is64bit(String host) { using (var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, host)) using (var key = reg.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\")) { return key.GetValue("ProgramFilesDir (x86)") !=null; } }
это решение на основе кода Microsoft в http://1code.codeplex.com/SourceControl/changeset/view/39074#842775. он использует методы расширения для легкого повторного использования кода.
некоторые возможные варианты использования показаны ниже:
bool bIs64BitOS = System.Environment.OSVersion.IsWin64BitOS(); bool bIs64BitProc = System.Diagnostics.Process.GetCurrentProcess().Is64BitProc(); //Hosts the extension methods public static class OSHelperTools { /// <summary> /// The function determines whether the current operating system is a /// 64-bit operating system. /// </summary> /// <returns> /// The function returns true if the operating system is 64-bit; /// otherwise, it returns false. /// </returns> public static bool IsWin64BitOS(this OperatingSystem os) { if (IntPtr.Size == 8) // 64-bit programs run only on Win64 return true; else// 32-bit programs run on both 32-bit and 64-bit Windows { // Detect whether the current process is a 32-bit process // running on a 64-bit system. return Process.GetCurrentProcess().Is64BitProc(); } } /// <summary> /// Checks if the process is 64 bit /// </summary> /// <param name="os"></param> /// <returns> /// The function returns true if the process is 64-bit; /// otherwise, it returns false. /// </returns> public static bool Is64BitProc(this System.Diagnostics.Process p) { // 32-bit programs run on both 32-bit and 64-bit Windows // Detect whether the current process is a 32-bit process // running on a 64-bit system. bool result; return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(p.Handle, out result)) && result); } /// <summary> /// The function determins whether a method exists in the export /// table of a certain module. /// </summary> /// <param name="moduleName">The name of the module</param> /// <param name="methodName">The name of the method</param> /// <returns> /// The function returns true if the method specified by methodName /// exists in the export table of the module specified by moduleName. /// </returns> static bool DoesWin32MethodExist(string moduleName, string methodName) { IntPtr moduleHandle = GetModuleHandle(moduleName); if (moduleHandle == IntPtr.Zero) return false; return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero); } [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] static extern IntPtr GetModuleHandle(string moduleName); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)]string procName); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process); }
вот прямой подход в C# с помощью DllImport от на этой странице.
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo); public static bool Is64Bit() { bool retVal; IsWow64Process(Process.GetCurrentProcess().Handle, out retVal); return retVal; }
Я использую следующий код. Примечание: это сделано для проекта AnyCPU.
public static bool Is32bitProcess(Process proc) { if (!IsThis64bitProcess()) return true; // We're in 32-bit mode, so all are 32-bit. foreach (ProcessModule module in proc.Modules) { try { string fname = Path.GetFileName(module.FileName).ToLowerInvariant(); if (fname.Contains("wow64")) { return true; } } catch { // What on earth is going on here? } } return false; } public static bool Is64bitProcess(Process proc) { return !Is32bitProcess(proc); } public static bool IsThis64bitProcess() { return (IntPtr.Size == 8); }
я использовал эту проверку с успехом на многих операционных системах:
private bool Is64BitSystem { get { return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%windir%\SysWOW64")); } }
эта папка всегда называется "SysWOW64", независимо от языка операционной системы. Это работает для .NET Framework 1.1 или выше.
Я нашел, что это лучший способ проверить платформу системы и процесс:
bool 64BitSystem = Environment.Is64BitOperatingSystem; bool 64BitProcess = Environment.Is64BitProcess;
первое свойство возвращает true для 64-разрядной системы и false для 32-разрядной. Второе свойство возвращает true для 64-разрядного процесса и false для 32-разрядного.
необходимость в этих двух свойствах заключается в том, что вы можете запускать 32-разрядные процессы в 64-разрядной системе, поэтому вам нужно будет проверить как систему, так и процесс.
все нормально, но это также должно работать от
env
:PROCESSOR_ARCHITECTURE=x86
..
PROCESSOR_ARCHITECTURE=AMD64
слишком легко, может быть ;-)
здесь Инструментарий Управления Windows (WMI) подход:
string _osVersion = ""; string _osServicePack = ""; string _osArchitecture = ""; ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_OperatingSystem"); ManagementObjectCollection collection = searcher.Get(); foreach (ManagementObject mbo in collection) { _osVersion = mbo.GetPropertyValue("Caption").ToString(); _osServicePack = string.Format("{0}.{1}", mbo.GetPropertyValue("ServicePackMajorVersion").ToString(), mbo.GetPropertyValue("ServicePackMinorVersion").ToString()); try { _osArchitecture = mbo.GetPropertyValue("OSArchitecture").ToString(); } catch { // OSArchitecture only supported on Windows 7/Windows Server 2008 } } Console.WriteLine("osVersion : " + _osVersion); Console.WriteLine("osServicePack : " + _osServicePack); Console.WriteLine("osArchitecture: " + _osArchitecture); ///////////////////////////////////////// // Test on Windows 7 64-bit // // osVersion : Microsoft Windows 7 Professional // osservicePack : 1.0 // osArchitecture: 64-bit ///////////////////////////////////////// // Test on Windows Server 2008 64-bit // --The extra r's come from the registered trademark // // osVersion : Microsoftr Windows Serverr 2008 Standard // osServicePack : 1.0 // osArchitecture: 64-bit ///////////////////////////////////////// // Test on Windows Server 2003 32-bit // --OSArchitecture property not supported on W2K3 // // osVersion : Microsoft(R) Windows(R) Server 2003, Standard Edition // osServicePack : 2.0 // osArchitecture:
OSInfo.Бит
using System; namespace CSharp411 { class Program { static void Main( string[] args ) { Console.WriteLine( "Operation System Information" ); Console.WriteLine( "----------------------------" ); Console.WriteLine( "Name = {0}", OSInfo.Name ); Console.WriteLine( "Edition = {0}", OSInfo.Edition ); Console.WriteLine( "Service Pack = {0}", OSInfo.ServicePack ); Console.WriteLine( "Version = {0}", OSInfo.VersionString ); Console.WriteLine( "Bits = {0}", OSInfo.Bits ); Console.ReadLine(); } } }
добавить следующий код в класс в вашем проекте:
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool wow64Process); public static int GetBit() { int MethodResult = ""; try { int Architecture = 32; if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6) { using (Process p = Process.GetCurrentProcess()) { bool Is64Bit; if (IsWow64Process(p.Handle, out Is64Bit)) { if (Is64Bit) { Architecture = 64; } } } } MethodResult = Architecture; } catch //(Exception ex) { //ex.HandleException(); } return MethodResult; }
используйте его так:
string Architecture = "This is a " + GetBit() + "bit machine";
используйте это, чтобы получить установленную архитектуру Windows:
string getOSArchitecture() { string architectureStr; if (Directory.Exists(Environment.GetFolderPath( Environment.SpecialFolder.ProgramFilesX86))) { architectureStr ="64-bit"; } else { architectureStr = "32-bit"; } return architectureStr; }
учитывая, что принятый ответ очень сложен. Есть более простые способы. Моя-это вариация анасвера александрудику. Учитывая, что 64-разрядная windows устанавливает 32-разрядные приложения в Program Files (x86), вы можете проверить, существует ли эта папка, используя переменные среды (чтобы компенсировать различные локализации)
например
private bool Is64BitSystem { get { return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES(X86)%")); } }
Это для меня быстрее и проще. Учитывая, что я также хочу получить доступ к определенному пути в этой папке на основе версии ОС.
просто посмотрите, если "C:\Program файлы (x86)" существует. Если нет, то вы находитесь на 32-битных ОС. Если это так, то ОС 64 бит (Windows Vista или Windows 7). Это кажется достаточно простым...
наслаждаться ;-)
Function Is64Bit() As Boolean Return My.Computer.FileSystem.SpecialDirectories.ProgramFiles.Contains("Program Files (x86)") End Function
Я использую:
Dim drivelet As String = Application.StartupPath.ToString If Directory.Exists(drivelet(0) & ":\Program Files (x86)") Then MsgBox("64bit") Else MsgBox("32bit") End if
Это возвращает путь, по которому запускается ваше приложение, если оно установлено в разных местах на компьютере. Кроме того, вы могли бы просто сделать общее
C:\
путь с 99,9% компьютеров там установлены окна вC:\
.