Como detectar a plataforma Windows de 64 bits com o .NET?

Em um aplicativo .NET 2.0 C #, uso o seguinte código para detectar a plataforma do sistema operacional:

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

Isso retorna “Win32NT”. O problema é que ele retorna “Win32NT” mesmo quando executado no Windows Vista de 64 bits.

Existe algum outro método para conhecer a plataforma correta (32 ou 64 bits)?

Observe que ele também deve detectar 64 bits quando executado como um aplicativo de 32 bits no Windows 64 bits.

IntPtr.Size não retornará o valor correto se estiver executando no .NET Framework 2.0 de 32 bits no Windows de 64 bits (ele retornará 32 bits).

Como Raymond Chen da Microsoft descreve, você precisa primeiro verificar se está sendo executado em um processo de 64 bits (acho que no .NET você pode fazer isso verificando IntPtr.Size), e se você estiver executando em um processo de 32 bits, você ainda tem que chamar a function Win API IsWow64Process. Se isso retornar true, você está executando em um processo de 32 bits no Windows de 64 bits.

Raymond Chen, da Microsoft: Como detectar programaticamente se você está executando no Windows de 64 bits

Minha solução:

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

O .NET 4 possui duas novas propriedades na class Environment, Is64BitProcess e Is64BitOperatingSystem . Curiosamente, se você usar o Reflector, verá que eles são implementados de maneira diferente nas versões de 32 bits e 64 bits do mscorlib. A versão de 32 bits retorna false para Is64BitProcess e chama IsWow64Process via P / Invoke para Is64BitOperatingSystem. A versão de 64 bits apenas retorna true para ambos.

Se você estiver usando o .NET Framework 4.0, é fácil:

 Environment.Is64BitOperatingSystem 

Consulte a propriedade Environment.Is64BitOperatingSystem (MSDN).

Esta é apenas uma implementação do que foi sugerido acima por Bruno Lopez, mas funciona no Win2k + todos os service packs do WinXP. Apenas imaginei que iria postar para que outras pessoas não o tivessem rolando à mão. (teria postado como um comentário, mas eu sou um novo usuário!)

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

A resposta completa é essa (tirada da resposta de stefan-mg, ripper234 e 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; } 

Primeiro verifique se você está em um processo de 64 bits. Se você não for, verifique se o processo de 32 bits é um Wow64Process.

A Microsoft colocou um exemplo de código para isso:

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

Se parece com isso:

  ///  /// The function determines whether the current operating system is a /// 64-bit operating system. ///  ///  /// The function returns true if the operating system is 64-bit; /// otherwise, it returns false. ///  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); } } ///  /// The function determins whether a method exists in the export /// table of a certain module. ///  /// The name of the module /// The name of the method ///  /// The function returns true if the method specified by methodName /// exists in the export table of the module specified by moduleName. ///  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); 

Há uma versão WMI disponível também (para testar máquinas remotas).

Você também pode verificar a variável de ambiente PROCESSOR_ARCHITECTURE .

Ele não existe ou está definido como “x86” no 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); } 

Do blog de Chriz Yuen

C # .Net 4.0 introduziu duas novas propriedades de ambiente Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;

Por favor tenha cuidado quando você usa estas duas propriedades. Teste no 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 

Tente isto:

 Environment.Is64BitOperatingSystem Environment.Is64BitProcess 

@foobar: Você está certo, é muito fácil;)

Em 99% dos casos, os desenvolvedores com histórico de administrador de sistema fraco não conseguem perceber a capacidade que a Microsoft sempre forneceu para qualquer pessoa enumerar o Windows.

Os administradores de sistemas sempre escreverão códigos melhores e mais simples quando se trata de tal ponto.

No entanto, uma coisa a notar, configuração de compilation deve ser AnyCPU para esta variável de ambiente para retornar os valores corretos nos sistemas corretos:

 System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") 

Isso retornará “X86” no Windows de 32 bits e “AMD64” no Windows de 64 bits.

Maneira mais rápida:

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

Nota: isso é muito direto.

Use estas duas variables ​​de ambiente (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 o post do blog HOWTO: Detectar Bitness do Processo .

Usando dotPeek ajuda a ver como o framework realmente faz isso. Com isso em mente, aqui está o que eu tenho:

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

Exemplo de uso:

 EnvironmentHelper.Is64BitOperatingSystem(); 

Eu preciso fazer isso, mas eu também preciso ser capaz como administrador remotamente, caso isso parece funcionar muito bem para mim:

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

Esta é uma solução baseada no código da Microsoft em http://1code.codeplex.com/SourceControl/changeset/view/39074#842775 . Ele usa methods de extensão para reutilização de código fácil.

Alguns usos possíveis são mostrados abaixo:

 bool bIs64BitOS = System.Environment.OSVersion.IsWin64BitOS(); bool bIs64BitProc = System.Diagnostics.Process.GetCurrentProcess().Is64BitProc(); //Hosts the extension methods public static class OSHelperTools { ///  /// The function determines whether the current operating system is a /// 64-bit operating system. ///  ///  /// The function returns true if the operating system is 64-bit; /// otherwise, it returns false. ///  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(); } } ///  /// Checks if the process is 64 bit ///  ///  ///  /// The function returns true if the process is 64-bit; /// otherwise, it returns false. ///  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); } ///  /// The function determins whether a method exists in the export /// table of a certain module. ///  /// The name of the module /// The name of the method ///  /// The function returns true if the method specified by methodName /// exists in the export table of the module specified by moduleName. ///  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); } 

Aqui está a abordagem direta em C # usando DllImport desta 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; } 

Eu estou usando o seguinte código. Nota: É feito para um projeto 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); } 

Eu usei essa verificação com sucesso em muitos sistemas operacionais:

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

Esta pasta é sempre chamada “SysWOW64”, não importa o idioma do sistema operacional. Isso funciona para o .NET Framework 1.1 ou superior.

Achei que esta é a melhor maneira de verificar a plataforma do sistema e o processo:

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

A primeira propriedade retorna true para o sistema de 64 bits e false para o de 32 bits. A segunda propriedade retorna true para o processo de 64 bits e false para 32 bits.

A necessidade dessas duas propriedades é porque você pode executar processos de 32 bits no sistema de 64 bits, portanto, será necessário verificar o sistema e o processo.

Tudo bem, mas isso também deve funcionar a partir de env :

 PROCESSOR_ARCHITECTURE=x86 

..

 PROCESSOR_ARCHITECTURE=AMD64 

Muito fácil, talvez 😉

Aqui está uma abordagem do Windows Management Instrumentation (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.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(); } } } 

Inclua o seguinte código em uma class em seu projeto:

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

Use assim:

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

Use isto para obter a arquitetura do Windows instalada:

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

Dado que a resposta aceita é muito complexa. Existem maneiras mais simples. O meu é uma variação do anaswer de alexandrudicu. Como as janelas de 64 bits instalam aplicativos de 32 bits em Arquivos de Programas (x86), você pode verificar se essa pasta existe, usando variables ​​de ambiente (para compensar diferentes localizações)

por exemplo

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

Isso para mim é mais rápido e simples. Dado que eu também gostaria de acessar um caminho específico sob essa pasta com base na versão do sistema operacional.

Basta ver se o “C: \ Program Files (x86)” existe. Se não, então você está em um sistema operacional de 32 bits. Em caso afirmativo, o SO é de 64 bits (Windows Vista ou Windows 7). Parece bastante simples …

Apreciar 😉

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

Eu uso:

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

Isso obtém o caminho onde o aplicativo é iniciado, caso você o tenha instalado em vários locais no computador. Além disso, você poderia apenas fazer o caminho geral C:\ já que 99,9% dos computadores têm o Windows instalado em C:\ .

Eu uso uma versão do seguinte:

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