web-dev-qa-db-fra.com

Comment détecter la plate-forme Windows 64 bits avec .NET?

Dans une application .NET 2.0 C #, j'utilise le code suivant pour détecter la plate-forme du système d'exploitation:

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

Cela retourne "Win32NT". Le problème est qu'il renvoie "Win32NT" même lorsqu'il est exécuté sur Windows Vista 64 bits.

Existe-t-il une autre méthode pour connaître la plate-forme correcte (32 ou 64 bits)?

Notez qu'il devrait également détecter 64 bits lorsqu'il est exécuté en tant qu'application 32 bits sous Windows 64 bits.

249
Marc

IntPtr.Size ne renverra pas la valeur correcte s'il est exécuté dans .NET Framework 2.0 32 bits sous Windows 64 bits (il renverrait 32 bits).

Comme Raymond Chen de Microsoft le décrit, vous devez d’abord vérifier si vous exécutez un processus 64 bits (je pense que vous pouvez le faire en vérifiant IntPtr.Size.) devez appeler la fonction WinWIss IsWow64Process. Si cela renvoie la valeur true, vous exécutez un processus 32 bits sous Windows 64 bits.

Raymond Chen de Microsoft: Comment détecter par programme si vous utilisez Windows 64 bits

Ma solution:

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;
    }
}
191
Stefan Schultze

.NET 4 a deux nouvelles propriétés dans la classe Environment, Is64BitProcess et Is64BitOperatingSystem . Fait intéressant, si vous utilisez Reflector, vous pouvez voir qu’elles sont implémentées différemment dans les versions 32 bits et 64 bits de mscorlib. La version 32 bits renvoie false pour Is64BitProcess et appelle IsWow64Process via P/Invoke pour Is64BitOperatingSystem. La version 64 bits renvoie simplement true pour les deux.

228
Phil Devaney

Si vous utilisez .NET Framework 4.0, rien de plus simple:

Environment.Is64BitOperatingSystem

Voir Environment.Is64BitOperatingSystem, propriété (MSDN).

88

Ceci est juste une implémentation de ce que Bruno Lopez a suggéré plus haut, mais fonctionne sur Win2k + tous les service packs WinXP. Je me suis dit que je le posterais pour que personne ne l'ait roulé à la main. (aurait posté comme un commentaire, mais je suis un nouvel utilisateur!)

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

La réponse complète est la suivante (tirée de la réponse de stefan-mg, de ripper234 et 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;
    } 

Commencez par vérifier si vous êtes dans un processus 64 bits. Si ce n'est pas le cas, vérifiez si le processus 32 bits est un processus Wow64.

49
Bruno Lopes

Microsoft a mis un exemple de code pour cela:

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

Cela ressemble à ceci:

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

Une version WMI est également disponible (pour tester les machines distantes).

41
synhershko

Vous pouvez également rechercher la variable d'environnement PROCESSOR_ARCHITECTURE.

Il n'existe pas ou est défini sur "x86" sous Windows 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);
}
16
Andrew Ensley

Du blog de Chriz Yuen

C # .Net 4.0 Introduit deux nouvelles propriétés d’environnement Environment.Is64BitOperatingSystem; Environment.Is64BitProcess;

S'il vous plaît soyez prudent lorsque vous utilisez ces deux propriétés. Test sur une machine Windows 7 64bits 

//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
12
electricalbah

Essaye ça:

Environment.Is64BitOperatingSystem

Environment.Is64BitProcess
11
user2235582

La façon la plus rapide:

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

Note:c'est très direct.

9
BobbyShaftoe

@foobar: Vous avez raison, c'est trop facile;)

Dans 99% des cas, les développeurs avec de faibles arrière-plans d'administrateur système ne réalisent finalement pas le pouvoir que Microsoft a toujours fourni à quiconque d'énumérer Windows.

Les administrateurs système écriront toujours un code plus simple et de meilleure qualité.

Néanmoins, une chose à noter, la configuration de construction doit être AnyCPU pour que cette variable d’environnement renvoie les valeurs correctes sur les systèmes appropriés:

System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")

Cela renverra "X86" sous Windows 32 bits et "AMD64" sous Windows 64 bits.

9
SomeSysadmin

Utiliser dotPeek aide à voir comment le framework le fait réellement. Dans cet esprit, voici ce que je propose:

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

Exemple d'utilisation:

EnvironmentHelper.Is64BitOperatingSystem();
6
Alexandru

Utilisez ces deux variables d’environnement (pseudo-code):

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
        }

Reportez-vous à la publication sur le blog HOWTO: Détecter les bits de processus.

6
Santhosh

J'ai utilisé cette vérification avec succès sur de nombreux systèmes d'exploitation:

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

Ce dossier est toujours nommé "SysWOW64", quelle que soit la langue du système d'exploitation. Cela fonctionne pour .NET Framework 1.1 ou supérieur.

4
Alexandru Dicu

Je dois le faire, mais je dois aussi pouvoir en tant qu'administrateur le faire à distance, dans les deux cas, cela semble fonctionner assez bien pour moi:

    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;
        }
    }
4
Julian Hall

Ceci est une solution basée sur le code de Microsoft à l’adresse http://1code.codeplex.com/SourceControl/changeset/view/39074#842775 . Il utilise des méthodes d'extension pour une réutilisation facile du code.

Quelques utilisations possibles sont indiquées ci-dessous:

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

Voici l'approche directe en C # utilisant DllImport depuis cette page .

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

J'utilise le code suivant. Note: C'est fait pour un projet Any CPU.

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

J'ai trouvé que c'était le meilleur moyen de vérifier la plate-forme du système et le processus:

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

La première propriété renvoie true pour un système 64 bits et false pour 32 bits . La seconde propriété renvoie true pour les processus 64 bits et false pour 32 bits.

La nécessité de ces deux propriétés tient au fait que vous pouvez exécuter des processus 32 bits sur un système 64 bits. Vous devez donc vérifier à la fois le système et le processus.

2
OmarElsherif

Tout va bien, mais cela devrait aussi fonctionner à partir de env:

PROCESSOR_ARCHITECTURE=x86

..

PROCESSOR_ARCHITECTURE=AMD64

Trop facile, peut-être ;-)

2
foobar

Voici une approche 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:
2
user1054695

Incluez le code suivant dans une classe de votre projet:

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

Utilisez-le comme suit:

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

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

Utilisez ceci pour obtenir l'architecture Windows installée:

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

Étant donné que la réponse acceptée est très complexe. Il y a des moyens plus simples. Le mien est une variante de anaswer ..__ d'Alexandrudicu . Étant donné que Windows 64 bits installent des applications 32 bits dans Program Files (x86), vous pouvez vérifier si ce dossier existe, en utilisant des variables d'environnement (pour compenser différentes localisations)

par exemple. 

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

Ceci est pour moi plus rapide et plus simple. Étant donné que je souhaite également accéder à un chemin spécifique sous ce dossier en fonction de la version du système d'exploitation. 

0
John Demetriou