281 votes

Comment détecter une plateforme Windows 64 bits avec .NET?

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

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

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

Y a-t-il une autre méthode pour connaître la plateforme 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 sur Windows 64 bits.

248voto

Phil Devaney Points 8595

.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.

5 votes

Au lieu de Reflector, pourquoi ne pas simplement télécharger la source. Ensuite, vous obtenez les commentaires et autres "notes".

3 votes

Selon la source de référence, cela fonctionne comme ceci: if (IntPtr.Size == 8) return true; if(!DoesWin32MethodExist(...,"IsWow64Process")) return false; return IsWow64Process(GetCurrentProcess()); (code pseudo)

5 votes

Bien. Si l'utilisateur utilise .NET 4.0, c'est certainement la réponse correcte (c'est-à-dire Environment.Is64BitOperatingSystem). -- À noter que cette propriété ne semble pas être présente dans .NET 3.5.

218voto

Stefan Schultze Points 4495

MISE À JOUR : Comme Joel Coehoorn et d'autres le suggèrent, à partir de .NET Framework 4.0, vous pouvez simplement vérifier Environment.Is64BitOperatingSystem.


IntPtr.Size ne renverra pas la valeur correcte si vous exécutez .NET Framework 2.0 en 32 bits sur Windows 64 bits (il renverrait 32 bits).

Comme le décrit Raymond Chen de Microsoft, vous devez d'abord vérifier si vous exécutez un processus 64 bits (je pense qu'en .NET vous pouvez le faire en vérifiant IntPtr.Size), et si vous exécutez un processus 32 bits, vous devez quand même appeler la fonction Win API IsWow64Process. Si cela renvoie true, vous exécutez un processus 32 bits sur Windows 64 bits.

Raymond Chen de Microsoft : Comment détecter de manière programmable si vous exécutez 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;
    }
}

8 votes

Lors de l'exécution sur un système d'exploitation 32 bits, tout appel à IsWow64Process lèvera une exception car cette entrée est manquante dans kernel32.dll. Vous devriez vérifier la solution affichée sur codeplex à 1code.codeplex.com/SourceControl/changeset/view/39074#842775. J'ai également une solution basée sur ce code répertoriée en bas de cette page, qui utilise des méthodes d'extension si vous souhaitez réutiliser le code.

8 votes

IsWow64Process a été introduit avec Win XP SP2. Ce code fonctionne bien si vous nécessitez XP SP2 ou toute version plus récente.

3 votes

@dmihailescu, vous pouvez simplement utiliser DoesWin32MethodExist avant d'appeler IsWow64Process, ce que fait l'implémentation .net 4.0 de is64BitOperatingSystem.

101voto

Si vous utilisez .NET Framework 4.0, c'est facile :

Environment.Is64BitOperatingSystem

Voir Propriété Environment.Is64BitOperatingSystem (MSDN).

2 votes

Pour les geeks, implémentation interne utilisant IsWow64Process(...) referencesource.microsoft.com/#mscorlib/system/…

51voto

dwhiteho Points 536

Ceci est simplement une implémentation de ce qui est suggéré ci-dessus par Bruno Lopez, mais fonctionne sur Win2k + tous les service packs WinXP. Je me suis juste dit que je le posterais afin que d'autres personnes n'aient pas à le faire à la main. (j'aurais pu le poster en 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;
}

49voto

Bruno Lopes Points 1606

La réponse complète est la suivante (prise à la fois des réponses de stefan-mg, ripper234 et 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 Wow64Process.

13 votes

Cela échouera sous Win2000 et WinXP SP1 et versions antérieures. Vous devez vérifier si la fonction IsWow64Process() existe avant de l'appeler, car elle n'a été introduite que dans XP SP2 et Vista/Win7.

2 votes

@utilisateur9876, est-ce que quelqu'un cible toujours ces systèmes antiques ?

5 votes

Ce exemple ne parvient pas à éliminer l'instance de Process renvoyée par Process.GetCurrentProcess().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X