2015-08-07 3 views
27

sto cercando un mezzo per rilevare se il mio C# applicazione è in esecuzione su Windows 10.Come posso rilevare se la mia applicazione è in esecuzione su Windows 10

Avevo sperato che Environment.OSVersion sarebbe fare il trucco, ma questo sembra restituire un Version di 6.3.9600.0 su Windows 8.1 e Windows 10.

Altre soluzioni come this non sembrano distinguere tra Windows 8 e Windows 10.

Qualche suggerimento?


Perché devo fare questo?

Perché sto utilizzando un controllo WebBrowser di WinForm per ospitare una pagina OAuth che si arresta in modo anomalo e brucia in versioni precedenti di IE (la mia app si collega a user's Nest account ...).

Per impostazione predefinita, il controllo WebBrowser emula IE7. Usando una chiave di registro, puoi dire che emula l'ultima versione di IE installata sul PC host. Tuttavia, lo value that worked fino a Windows 8.1 (e le versioni preliminari di Windows 10) non funziona nella versione finale di Windows 10.

+5

Hai [manifestare l'app] (https://msdn.microsoft.com/en-us/library/windows /desktop/dn481241%28v=vs.85%29.aspx) per Windows 10? – GSerg

+0

Esegui il programma utilizzando la modalità di compatibilità? – Graffito

+0

Ci sono altri modi per ottenere queste informazioni, controlla questo post http://stackoverflow.com/questions/6331826/get-os-version-friendly-name-in-c-sharp – Rahul

risposta

21

Se si guarda al Registro di sistema si trovano nome dell'ambiente:

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

Ad esempio il mio nome prodotto è Windows 10 Home:

Registry

Con questo codice si ottiene se 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"); 
} 

Nota: Aggiungi ai tuoi using Microsoft.Win32; usings.

+1

Non sono sicuro che le app del negozio possano accedere al registro ... – Rawling

+0

@Rawling - Nel mio scenario si tratta di un'app WinForms vecchia scuola, installata tramite ClickOnce –

+4

@RichardEverett Punto giusto! I bambini di questi tempi e le loro "app", non lo so ... :) – Rawling

1

Hai provato di seguito? [È necessario aggiungere un riferimento a Microsoft.VisulaBasic dll]

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

Sulla mia macchina dà, Microsoft Windows 7 Ultimate

+1

questo è deprezzato in Windows 10. – Claies

+0

@Claies, non ho idea di ciò ma questo fa schifo quindi :) – Rahul

+3

Inoltre ... Preferisco evitare di aggiungere un riferimento VisualBasic al mio progetto C#. –

14

Sotto il cofano, Environment.OSVersion utilizza il GetVersionEx function, che è stato deprecato. La documentazione avverte del comportamento osservato:

Le applicazioni non manifestate per Windows 8.1 o Windows 10 restituiranno il valore della versione del sistema operativo Windows 8 (6.2).

La documentazione continua a raccomandare:

Identificazione del sistema operativo corrente di solito non è il modo migliore per determinare se una particolare caratteristica del sistema operativo è presente. Ciò è dovuto al fatto che il sistema operativo potrebbe aver aggiunto nuove funzionalità in una DLL ridistribuibile. Anziché utilizzare GetVersionEx per determinare la piattaforma del sistema operativo o il numero di versione, verificare la presenza della funzione stessa.

Se la raccomandazione di cui sopra non è appropriato per il vostro caso, e si vuole davvero controllare la versione attuale del sistema operativo in esecuzione, quindi la documentazione fornisce anche un suggerimento su questo:

Per confrontare il sistema attuale versione a una versione richiesta, utilizzare la funzione VerifyVersionInfo invece di utilizzare GetVersionEx per eseguire il confronto da soli.

L'articolo richiesto è inviato un soluzione di lavoro utilizzando la funzione diVerifyVersionInfo: Version Helper API for .NET.

Dare pieno credito per l'autore di questo articolo, il seguente frammento di codice dovrebbe fornire il comportamento che state cercando:

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

Diniego: Non ho ancora Windows 10, quindi mi rifugio' t testato il codice in Windows 10.

+3

Da MSDN: "In Windows 10, anche la funzione VerifyVersionInfo è stata deprecata.Tuttavia è ancora possibile chiamare le funzioni deprecate, se l'applicazione esegue non specificamente target Windows 8.1 o Windows 10, si otterrà la versione di Windows 8 (6.2.0.0). " –

+0

https://msdn.microsoft.com/en-ca/library/windows/desktop/dn481241(v=vs.85) .aspx –

+0

Non funziona, restituendo ancora 6.2 per Win10! "Windows 10: VerifyVersionInfo restituisce false quando viene chiamato ...." –

18

risposta

Usa Environment.OSVersion e aggiungere un'applicazione file manifesto con le pertinenti supportedOS elementi non commentati.

ad es. aggiungere questo sotto < asmv1: assemblaggio >

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

Motivo

Non mi piace la risposta da @Mitat Koyuncu perché è utilizza il Registro inutilmente e come accennato nei commenti utilizza inaffidabili parsing della stringa.

Anche la risposta di @sstan non mi piace perché utilizza codice di terze parti e necessita comunque dell'applicazione manifest.

Da MSDN:

di Windows 10: VerifyVersionInfo restituisce false quando chiamato da applicazioni che non hanno una compatibilità manifesta per Windows 8.1 o Windows 10 se il parametro lpVersionInfo è impostato in modo che specifica Windows 8.1 o Windows 10, anche se la versione corrente del sistema operativo è 01835 o 1030. In particolare, VerifyVersionInfo ha il seguente comportamento:

• Se l'applicazione non ha manifest, VerifyVersionInfo si comporta come se la versione del sistema operativo fosse Windows 8 (6.2).

• Se l'applicazione contiene un GUID che corrisponde a Windows 8.1, VerifyVersionInfo si comporta come se la versione del sistema operativo fosse Windows 8.1 (6.3).

• Se l'applicazione dispone di un manifesto che contiene il GUID che corrisponde a Windows 10, VerifyVersionInfo si comporta come se la versione del sistema operativo è Windows 10 (10.0).

Il motivo è perché VerifyVersionInfo è deprecato in Windows 10.

Ho testato su Windows 10 e in effetti Environment.OSVersion funziona esattamente come previsto quando l'app.Manifest contiene il relativo GUID come sopra. Questo è probabilmente il motivo per cui non sono stati modificati o deprecati da .Net Framework.

+4

Questo è l'approccio corretto, ufficiale. Vorrei sottolineare agli altri che durante il test con 'app.manifest', assicurati che sia effettivamente nella tua cartella di output. Quando nella configurazione di debug, il mio non è stato copiato in 'bin/Debug'. Pensavo che l'app.manifest non funzionasse fino a quando non ho provato il rilascio e ho scavato un po 'di più. –

+0

ha funzionato per me. Stavo mostrando NT versione 6.2 fino a quando ho aggiunto il precedente a app.manifest. –

4

Suggerisco di utilizzare il registro per trovare i valori desiderati. Microsoft ha cambiato il modo in cui Windows 10 è elencato nel registro in modo che il codice debba adattarsi per quello.

Ecco il codice che ho usi, che identifica correttamente Windows 10 così:

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

Bello! Questo ha fatto il lavoro per me.Non si è preoccupato di controllare nient'altro che il 'CurrentMajorVersionNumber'; l'app aveva solo bisogno di sapere se era in esecuzione su Win10 o meno. Se la chiave del Registro di sistema non esiste perché è una versione precedente, beh, la missione compiuta direi. – Nyerguds