Benoît Laut
Développement x86 et x64 avec le Framework .Net
Aujourd’hui nous sommes dans une période de transition où 2 types de systèmes d’exploitation cohabitent, les OS 32bits et les OS 64bits. Je vous propose de découvrir leurs spécificités afin de les prendre en compte dans vos applications.
Par Benoît Laut publié le 05/07/2010 à 07:48, lu 4861 fois, 6 pages
 5 | 64Bits et la CLR 2.0
Nous avons vu dans le chapitre précédent que les méthodes d’accès explicite aux répertoires 32bits d’un OS 64bits, sont apparues avec le Framework 4.0. De la même manière, les propriétés permettant de savoir si le process de l’application est en 64bit ou si l’OS est 64bits ne sont pas disponibles avec les Framework 2.0, 3.0 ou 3.5.
Pour savoir si le process tourne en 64 ou en 32bits, il suffit de tester la taille d’un pointeur, comme nous l’indique David Catuhe sur son blog. Si IntPtr.Size vaut 4 alors c’est du x86, si ça vaut 8, c’est du x64.
Pour savoir si l’OS est en 32 ou en 64, c’est un peu plus compliqué. Pour trouver la réponse, un petit coup de Reflector sur mscorlib et sur la classe Environment du Framework 4.0 nous aide beaucoup… Voici ce que nous obtenons :

public static bool Is64BitOperatingSystem

{

    [SecuritySafeCritical]

    get

    {

        bool flag;

        return ((Win32Native.DoesWin32MethodExist("kernel32.dll", "IsWow64Process")

            && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out flag)) && flag);

    }

}

Que fait exactement ce code ?
Dans un premier temps, il vérifie que la dll kernel32.dll contient bien une méthode IsWow64Process. Si elle existe alors on appelle cette méthode en lui donnant le process courant. Cette méthode renvoie true si le process de l’application est en 32bits. Ici nous voyons bien que ce code ne fonctionnera pas pour une application qui tourne dans un process 64bits, car la méthode IsWow64Process va nous retourner false…
Alors comment fait exactement le Framework 4.0 dans ce cas ?
Une chose que nous avons oublié ici, c’est que mscorlib existe en 2 versions… 1 version 32bits et une version 64bits. Le code que nous venons de réflecter est le code de la version 32bits. Si notre application s’exécute en 64bits ce sera mscorlib en version 64bits qui sera chargé.
Voilà ce que nous trouvons en décompilant la propriété Is64BitOperatingSystem de la version 64bits de mscorlib :

public static bool Is64BitOperatingSystem

{

    [SecuritySafeCritical]

    get

    {

        return true;

    }

}

Une dll 64bits s’exécute forcément sur un OS 64bits, donc si on lui demande si l’OS est 64bits elle ne se pose pas de question et retourne true.
Voici le code que nous devons donc écrire en framework 3.5 :

public static bool Is64BitOperatingSystem

{

    [SecuritySafeCritical]

    get

    {

        bool flag;

        return IntPtr.Size == 8 || ((Win32Native.DoesWin32MethodExist("kernel32.dll", "IsWow64Process")

            && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out flag)) && flag);

    }

}

Si la taille du pointeur est de 8 alors on est sur un OS 64bits, sinon on appelle la méthode IsWow64Process.
Et maintenant le reste du code de la classe Win32Native :

[SuppressUnmanagedCodeSecurity, SecurityCritical]

    internal static class Win32Native

    {

 

 

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        internal static extern IntPtr GetCurrentProcess();

 

 

        [return: MarshalAs(UnmanagedType.Bool)]

        [DllImport("kernel32.dll", SetLastError = true)]

        internal static extern bool IsWow64Process([In] IntPtr hSourceProcessHandle, [Out] out bool isWow64);

 

        [SecurityCritical]

        internal static bool DoesWin32MethodExist(string moduleName, string methodName)

        {

            IntPtr moduleHandle = GetModuleHandle(moduleName);

            if (moduleHandle == IntPtr.Zero)

            {

                return false;

            }

            return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);

        }

 

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail),

        DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        private static extern IntPtr GetModuleHandle(string moduleName);

 

 

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]

        private static extern IntPtr GetProcAddress(IntPtr hModule, string methodName);

    }

 
» Démarrer une discussion