remarks cref c# windows 64bit .net-2.0 platform-detection

c# - cref - ¿Cómo detectar la plataforma Windows de 64 bits con.NET?



remarks c# (29)

En una aplicación .NET 2.0 C #, utilizo el siguiente código para detectar la plataforma del sistema operativo:

string os_platform = System.Environment.OSVersion.Platform.ToString();

Esto devuelve "Win32NT". El problema es que devuelve "Win32NT" incluso cuando se ejecuta en Windows Vista de 64 bits.

¿Hay algún otro método para conocer la plataforma correcta (32 o 64 bits)?

Tenga en cuenta que también debe detectar 64 bits cuando se ejecuta como una aplicación de 32 bits en Windows 64 bits.


.NET 4 tiene dos nuevas propiedades en la clase de entorno, Is64BitProcess e Is64BitOperatingSystem . Curiosamente, si usa Reflector puede ver que se implementan de manera diferente en las versiones de 32 bits y 64 bits de mscorlib. La versión de 32 bits devuelve false para Is64BitProcess y llama a IsWow64Process a través de P / Invoke para Is64BitOperatingSystem. La versión de 64 bits solo devuelve true para ambos.


@foobar: Tienes razón, es demasiado fácil;)

En el 99% de los casos, los desarrolladores con antecedentes de administrador de sistemas débiles finalmente no se dan cuenta del poder que Microsoft siempre ha brindado para que cualquiera pueda enumerar Windows.

Los administradores del sistema siempre escribirán un código mejor y más simple cuando se trata de tal punto.

Sin embargo, una cosa a tener en cuenta, la configuración de compilación debe ser AnyCPU para que esta variable de entorno devuelva los valores correctos en los sistemas correctos:

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

Esto devolverá "X86" en Windows de 32 bits y "AMD64" en Windows de 64 bits.


Aquí está el enfoque directo en C # usando DllImport desde esta página .

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


Aquí hay un enfoque de Instrumental de administración de 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:


Dado que la respuesta aceptada es muy compleja. Hay formas más simples. El mío es una variación de la respuesta de alexandrudicu. Dado que las ventanas de 64 bits instalan aplicaciones de 32 bits en Archivos de programa (x86), puede verificar si esa carpeta existe, usando variables de entorno (para compensar diferentes localizaciones)

p.ej

private bool Is64BitSystem { get { return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES(X86)%")); } }

Esto para mí es más rápido y más simple. Dado que también deseo acceder a una ruta específica en esa carpeta basada en la versión del sistema operativo.


Del blog Chriz Yuen.

C # .Net 4.0 introdujo dos nuevas propiedades de entorno Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;

Por favor tenga cuidado cuando use estos dos bienes. Prueba en 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


Descubrí que esta es la mejor manera de verificar la plataforma del sistema y el proceso:

bool 64BitSystem = Environment.Is64BitOperatingSystem; bool 64BitProcess = Environment.Is64BitProcess;

La primera propiedad devuelve true para el sistema de 64 bits y false para 32 bits. La segunda propiedad devuelve true para el proceso de 64 bits y false para 32 bits.

La necesidad de estas dos propiedades se debe a que puede ejecutar procesos de 32 bits en un sistema de 64 bits, por lo que deberá verificar tanto el sistema como el proceso.


Disfrutar ;-)

Function Is64Bit() As Boolean Return My.Computer.FileSystem.SpecialDirectories.ProgramFiles.Contains("Program Files (x86)") End Function


El uso de dotPeek ayuda a ver cómo el framework realmente lo hace. Con eso en mente, esto es lo que he encontrado:

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

Ejemplo de uso:

EnvironmentHelper.Is64BitOperatingSystem();


Esta es una solución basada en el código de Microsoft en 1code.codeplex.com/SourceControl/changeset/view/39074#842775 . Utiliza métodos de extensión para reutilizar el código fácilmente.

Algunos posibles usos se muestran a continuación:

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


Esto es solo una implementación de lo que se sugiere anteriormente por Bruno Lopez, pero funciona en Win2k + todos los paquetes de servicio de WinXP. Solo pensé que lo publicaría para que otras personas no lo hicieran rodar a mano. (Habría publicado como un comentario, pero soy un nuevo usuario!)

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


Estoy usando el siguiente código. Nota: Está hecho para un proyecto 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); }


Incluya el siguiente código en una clase en su proyecto:

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

Úsalo así:

string Architecture = "This is a " + GetBit() + "bit machine";


IntPtr.Size no devolverá el valor correcto si se ejecuta en .NET Framework 2.0 de 32 bits en Windows de 64 bits (devolvería 32 bits).

Como lo describe Raymond Chen de Microsoft, primero debe verificar si se ejecuta en un proceso de 64 bits (creo que en .NET puede hacerlo marcando IntPtr.Size), y si está ejecutando en un proceso de 32 bits, todavía Hay que llamar a la función Win API IsWow64Process. Si esto se vuelve verdadero, se está ejecutando en un proceso de 32 bits en Windows de 64 bits.

Raymond Chen de Microsoft: cómo detectar mediante programación si está ejecutando en Windows de 64 bits

Mi solución:

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


La manera mas rapida:

if(IntPtr.Size == 8) { // 64 bit machine } else if(IntPtr.Size == 4) { // 32 bit machine }

Nota: esto es muy directo.


La respuesta completa es la siguiente (tomada de stefan-mg, ripper234 y la respuesta de 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; }

Primero verifica si estás en un proceso de 64 bits. Si no lo está, compruebe si el proceso de 32 bits es un Wow64Process.


Microsoft ha puesto un ejemplo de código para esto:

1code.codeplex.com/SourceControl/changeset/view/39074#842775

Se parece a esto:

/// <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);

También hay una versión de WMI disponible (para probar máquinas remotas).


Necesito hacer esto, pero también necesito poder como administrador hacerlo de forma remota, en cualquier caso, esto parece funcionar muy bien para mí:

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


Prueba esto:

Environment.Is64BitOperatingSystem Environment.Is64BitProcess



Simplemente vea si existe el "C: / Archivos de programa (x86)". Si no, entonces estás en un sistema operativo de 32 bits. Si lo hace, entonces el sistema operativo es de 64 bits (Windows Vista o Windows 7). Parece bastante simple ...


También puede verificar la variable de entorno PROCESSOR_ARCHITECTURE .

O bien no existe o está configurado en "x86" en Windows de 32 bits.

private int GetOSArchitecture() { string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? 32 : 64); }


Todo bien, pero esto también debería funcionar desde env :

PROCESSOR_ARCHITECTURE=x86

..

PROCESSOR_ARCHITECTURE=AMD64

Demasiado fácil, tal vez ;-)


Use esto para obtener la arquitectura de Windows instalada:

string getOSArchitecture() { string architectureStr; if (Directory.Exists(Environment.GetFolderPath( Environment.SpecialFolder.ProgramFilesX86))) { architectureStr ="64-bit"; } else { architectureStr = "32-bit"; } return architectureStr; }


Utilicé este cheque con éxito en muchos sistemas operativos:

private bool Is64BitSystem { get { return Directory.Exists(Environment.ExpandEnvironmentVariables(@"%windir%/SysWOW64")); } }

Esta carpeta siempre se llama "SysWOW64", sin importar el idioma del sistema operativo. Esto funciona para .NET Framework 1.1 o superior.


Utilice estas dos variables de entorno (pseudo código):

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 }

Consulte la entrada de blog HOWTO: Detect Process Bitness .


Yo suelo:

Dim drivelet As String = Application.StartupPath.ToString If Directory.Exists(drivelet(0) & ":/Program Files (x86)") Then MsgBox("64bit") Else MsgBox("32bit") End if

Esto obtiene la ruta donde se inicia su aplicación en caso de que la tenga instalada en varios lugares de la computadora. Además, solo puede hacer la ruta general C:/ ya que el 99.9% de las computadoras tienen Windows instalado en C:/ .


Yo uso una versión de lo siguiente:

public static bool Is64BitSystem() { if (Directory.Exists(Environment.GetEnvironmentVariable("Program Files (x86)"))) return true; else return false; }


OSInfo.Bits

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