web-dev-qa-db-fra.com

Comment puis-je détecter si mon application fonctionne sous Windows 10

Je cherche un moyen de détecter si mon application C # fonctionne sur Windows 10.

J'avais espéré que Environment.OSVersion ferait l'affaire, mais cela semble renvoyer un Version de 6.3.9600.0 sur Windows 8.1 et Windows 10.

D'autres solutions telles que this ne semblent pas non plus faire la distinction entre Windows 8 et Windows 10.

Aucune suggestion?


Pourquoi dois-je faire ça?

Parce que j'utilise un contrôle WinForms WebBrowser pour héberger une page OAuth qui se bloque et brûle dans les anciennes versions IE (mon application se connecte à un compte Nest de l'utilisateur ...).

Par défaut, le contrôle WebBrowser émule IE7. À l'aide d'une clé de registre, vous pouvez lui indiquer d'émuler la dernière version de IE installée sur le PC hôte. Cependant, la valeur qui a fonctionné jusqu'à Windows 8.1 (et les versions préliminaires de Windows 10) ne fonctionne pas dans la version finale de Windows 10.

37
Richard Everett

Si vous regardez le registre, vous trouverez le nom de l'environnement:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName

Par exemple, le nom de mon produit est Windows 10 Home:

Registry

Avec ce code, vous obtenez si c'est Windows 10:

 static bool IsWindows10()
 {
     var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

     string productName = (string)reg.GetValue("ProductName");

     return productName.StartsWith("Windows 10");
 }

Remarque: ajoutez using Microsoft.Win32; à vos utilisations.

28
Mitat Koyuncu

Réponse

Utilisation Environment.OSVersion et ajoutez un fichier manifeste d'application avec les éléments supportedOS pertinents non commentés.

par exemple. ajoutez ceci sous <asmv1: Assembly>

<compatibility xmlns="urn:schemas-Microsoft-com:compatibility.v1"> 
    <application> 
        <!-- Windows 10 --> 
        <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        <!-- Windows 8.1 -->
        <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
        <!-- Windows Vista -->
        <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
        <!-- Windows 7 -->
        <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
        <!-- Windows 8 -->
        <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
    </application> 
</compatibility>

Raison

Je n'aime pas la réponse de @Mitat Koyuncu car utilise le registre inutilement et comme mentionné dans les commentaires utilise une analyse de chaîne non fiable.

Je n'aime pas non plus la réponse de @sstan car il utilise du code tiers et il a quand même besoin du manifeste de l'application.

De MSDN :

Windows 10: VerifyVersionInfo renvoie false lorsqu'il est appelé par des applications qui n'ont pas de manifeste de compatibilité pour Windows 8.1 ou Windows 10 si le paramètre lpVersionInfo est défini de sorte qu'il spécifie Windows 8.1 ou Windows 10, même lorsque la version actuelle du système d'exploitation est Windows 8.1 ou Windows 10. Plus précisément, VerifyVersionInfo a le comportement suivant:

• Si l'application n'a pas de manifeste, VerifyVersionInfo se comporte comme si la version du système d'exploitation était Windows 8 (6.2).

• Si l'application a un manifeste qui contient le GUID qui correspond à Windows 8.1, VerifyVersionInfo se comporte comme si l'opération la version du système est Windows 8.1 (6.3).

• Si l'application a un manifeste qui contient le GUID qui correspond à Windows 10, VerifyVersionInfo se comporte comme si l'opération la version du système est Windows 10 (10.0).

La raison en est que VerifyVersionInfo est déconseillé dans Windows 10.

J'ai testé sur Windows 10 et en effet Environment.OSVersion fonctionne exactement comme prévu lorsque app.Manifest contient le GUID comme ci-dessus. C'est probablement la raison pour laquelle ils ne l'ont pas modifié ou déconseillé de .Net Framework.

33
Dave Williams

Sous le capot, Environment.OSVersion utilise la fonction GetVersionEx , qui est obsolète. La documentation met en garde contre le comportement que vous avez observé:

Les applications non manifestées pour Windows 8.1 ou Windows 10 renverront la valeur de version du système d'exploitation Windows 8 (6.2).

La documentation continue de recommander:

L'identification du système d'exploitation actuel n'est généralement pas la meilleure façon de déterminer si une fonction particulière du système d'exploitation est présente. Cela est dû au fait que le système d'exploitation a pu avoir de nouvelles fonctionnalités ajoutées dans une DLL redistribuable. Plutôt que d'utiliser GetVersionEx pour déterminer la plate-forme du système d'exploitation ou le numéro de version, testez la présence de la fonctionnalité elle-même.

Si la recommandation ci-dessus ne convient pas à votre cas et que vous souhaitez vraiment vérifier la version du système d'exploitation en cours d'exécution, la documentation fournit également un indice à ce sujet:

Pour comparer la version actuelle du système à une version requise, utilisez la fonction VerifyVersionInfo au lieu d'utiliser GetVersionEx pour effectuer vous-même la comparaison.

L'article suivant a publié une solution de travail utilisant la fonction VerifyVersionInfo : API Version Helper pour .NET .

En accordant un crédit complet à l'auteur de cet article, l'extrait de code suivant devrait fournir le comportement que vous recherchez:

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(IsWindowsVersionOrGreater(6, 3, 0)); // Plug in appropriate values.
    }

    [StructLayout(LayoutKind.Sequential)]
    struct OsVersionInfoEx
    {
        public uint OSVersionInfoSize;
        public uint MajorVersion;
        public uint MinorVersion;
        public uint BuildNumber;
        public uint PlatformId;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string CSDVersion;
        public ushort ServicePackMajor;
        public ushort ServicePackMinor;
        public ushort SuiteMask;
        public byte ProductType;
        public byte Reserved;
    }

    [DllImport("kernel32.dll")]
    static extern ulong VerSetConditionMask(ulong dwlConditionMask,
       uint dwTypeBitMask, byte dwConditionMask);
    [DllImport("kernel32.dll")]
    static extern bool VerifyVersionInfo(
        [In] ref OsVersionInfoEx lpVersionInfo,
        uint dwTypeMask, ulong dwlConditionMask);

    static bool IsWindowsVersionOrGreater(
        uint majorVersion, uint minorVersion, ushort servicePackMajor)
    {
        OsVersionInfoEx osvi = new OsVersionInfoEx();
        osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
        osvi.MajorVersion = majorVersion;
        osvi.MinorVersion = minorVersion;
        osvi.ServicePackMajor = servicePackMajor;
        // These constants initialized with corresponding definitions in
        // winnt.h (part of Windows SDK)
        const uint VER_MINORVERSION = 0x0000001;
        const uint VER_MAJORVERSION = 0x0000002;
        const uint VER_SERVICEPACKMAJOR = 0x0000020;
        const byte VER_GREATER_EQUAL = 3;
        ulong versionOrGreaterMask = VerSetConditionMask(
            VerSetConditionMask(
                VerSetConditionMask(
                    0, VER_MAJORVERSION, VER_GREATER_EQUAL),
                VER_MINORVERSION, VER_GREATER_EQUAL),
            VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
        uint versionOrGreaterTypeMask = VER_MAJORVERSION |
            VER_MINORVERSION | VER_SERVICEPACKMAJOR;
        return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask,
            versionOrGreaterMask);
    }
}

Avertissement: je n'ai pas encore Windows 10, donc je n'ai pas testé le code sur Windows 10.

15
sstan

Je suggère d'utiliser le registre pour trouver les valeurs que vous souhaitez. Microsoft a changé la façon dont Windows 10 est répertorié dans le registre, le code doit donc s'adapter à cela.

Voici le code que j'utilise, qui identifie également correctement Windows 10:

namespace Inspection
{
    /// <summary>
    /// Static class that adds convenient methods for getting information on the running computers basic hardware and os setup.
    /// </summary>
    public static class ComputerInfo
    {
        /// <summary>
        ///     Returns the Windows major version number for this computer.
        /// </summary>
        public static uint WinMajorVersion
        {
            get
            {
                dynamic major;
                // The 'CurrentMajorVersionNumber' string value in the CurrentVersion key is new for Windows 10, 
                // and will most likely (hopefully) be there for some time before MS decides to change this - again...
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out major))
                {
                    return (uint) major;
                }

                // When the 'CurrentMajorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
                dynamic version;
                if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
                    return 0;

                var versionParts = ((string) version).Split('.');
                if (versionParts.Length != 2) return 0;
                uint majorAsUInt;
                return uint.TryParse(versionParts[0], out majorAsUInt) ? majorAsUInt : 0;
            }
        }

        /// <summary>
        ///     Returns the Windows minor version number for this computer.
        /// </summary>
        public static uint WinMinorVersion
        {
            get
            {
                dynamic minor;
                // The 'CurrentMinorVersionNumber' string value in the CurrentVersion key is new for Windows 10, 
                // and will most likely (hopefully) be there for some time before MS decides to change this - again...
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber",
                    out minor))
                {
                    return (uint) minor;
                }

                // When the 'CurrentMinorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
                dynamic version;
                if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
                    return 0;

                var versionParts = ((string) version).Split('.');
                if (versionParts.Length != 2) return 0;
                uint minorAsUInt;
                return uint.TryParse(versionParts[1], out minorAsUInt) ? minorAsUInt : 0;
            }
        }

        /// <summary>
        ///     Returns whether or not the current computer is a server or not.
        /// </summary>
        public static uint IsServer
        {
            get
            {
                dynamic installationType;
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType",
                    out installationType))
                {
                    return (uint) (installationType.Equals("Client") ? 0 : 1);
                }

                return 0;
            }
        }

        private static bool TryGetRegistryKey(string path, string key, out dynamic value)
        {
            value = null;
            try
            {
                var rk = Registry.LocalMachine.OpenSubKey(path);
                if (rk == null) return false;
                value = rk.GetValue(key);
                return value != null;
            }
            catch
            {
                return false;
            }
        }
    }
}
7
Spiralis

Vous ne pouvez pas utiliser les fonctions Version Helper? https://msdn.Microsoft.com/en-us/library/windows/desktop/dn424972 (v = vs.85) .aspx

IsWindows10OrGreater

Indique si la version actuelle du système d'exploitation correspond ou est supérieure à la version Windows 10. Pour Windows 10, IsWindows10OrGreater renvoie false sauf si l'application contient un manifeste qui comprend une section de compatibilité qui contient le GUID qui désigne Windows 10.

et ajoutez les GUID: https://msdn.Microsoft.com/en-ca/library/windows/desktop/dn481241 (v = vs.85) .aspx

2
juFo

Essaye celui-là:

string subKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion";
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine;
Microsoft.Win32.RegistryKey skey = key.OpenSubKey(subKey);

string name = skey.GetValue("ProductName").ToString();

puis vous pouvez simplement utiliser une clause if:

if(name.Contains("Windows 10"))
{
    //... procedures
}
else
{
   //... procedures
}

Avez-vous essayé ci-dessous? [Vous devez ajouter une référence à Microsoft.VisulaBasic dll]

new Microsoft.VisualBasic.Devices.ComputerInfo().OSFullName

Sur ma machine, cela donne Microsoft Windows 7 Ultimate

1
Rahul