2016-06-08 42 views
10

Sto cercando di recuperare la versione di Windows con C# sul mio computer Windows 10.Ottenere la versione del sistema operativo Windows a livello di programmazione

ottengo sempre quei valori (con C# \ C++):

Maggiore: 6

Minore: 2

Quale è Windows 8 OS, accordingly to MSDN

C# code:

var major = OperatingSystem.Version.Major 
var minor = OperatingSystem.Version.Minor 

codice C++

void print_os_info() 
{ 
    //http://stackoverflow.com/questions/1963992/check-windows-version 
    OSVERSIONINFOW info; 
    ZeroMemory(&info, sizeof(OSVERSIONINFOW)); 
    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); 

    LPOSVERSIONINFOW lp_info = &info; 
    GetVersionEx(lp_info); 

    printf("Windows version: %u.%u\n", info.dwMajorVersion, info.dwMinorVersion); 
} 

di Windows 10 supponiamo di essere con quelli:

Maggiore: 10

minore: 0 *

  • (Quando mi sto prendendo un file di dump dal processo in esecuzione posso vedere che la versione del sistema operativo di tale file è impostato su 10,0)

costruito da: 10.0.10586.0 (th2_release.151029-1700)

Cosa mi manca qui?

+2

Questo potrebbe essere rilevante: dalla pagina che hai collegato a "Applicazioni non manifestate per Windows 8.1 o Windows 10 restituirà il valore della versione del sistema operativo Windows 8 (6.2)." – stuartd

+0

Suppongo che tu abbia ragione, l'ho persa –

+0

La mia applicazione è console, quindi ho solo questo file App.config (nessun gruppo) –

risposta

1

come la risposta accettata è solo per C#, ecco una soluzione per C++.

Utilizza RtlGetVersion nel ntdll.dll che utilizza la stessa struttura di GetVersionEx (il nome è diverso, ma gli elementi sono gli stessi) e fornisce la versione corretta. Poiché questa funzione viene normalmente utilizzata per lo sviluppo del driver, la funzione viene dichiarata nel DDK e non nell'SDK. Quindi ho usato una soluzione dinamica per chiamare la funzione. Si prega di essere consapevoli del fatto che il ntdll.dll viene caricato e rilasciato in ogni chiamata. Quindi se hai bisogno della funzione più spesso, mantieni la libreria caricata.

La struttura che pOSversion sta puntando deve essere inizializzata come per GetVersionEx.

BOOL GetTrueWindowsVersion(OSVERSIONINFOEX* pOSversion) 
{ 
    // Function pointer to driver function 
    NTSTATUS (WINAPI *pRtlGetVersion)(
     PRTL_OSVERSIONINFOW lpVersionInformation) = NULL; 

    // load the System-DLL 
    HINSTANCE hNTdllDll = LoadLibrary("ntdll.dll"); 

    // successfully loaded? 
    if (hNTdllDll != NULL) 
    { 
     // get the function pointer to RtlGetVersion 
     pRtlGetVersion = (NTSTATUS (WINAPI *)(PRTL_OSVERSIONINFOW)) 
      GetProcAddress (hNTdllDll, "RtlGetVersion"); 

     // if successfull then read the function 
     if (pRtlGetVersion != NULL) 
     pRtlGetVersion((PRTL_OSVERSIONINFOW)pOSversion); 

     // free the library 
     FreeLibrary(hNTdllDll); 
    } // if (hNTdllDll != NULL) 

    // if function failed, use fallback to old version 
    if (pRtlGetVersion == NULL) 
     GetVersionEx((OSVERSIONINFO*)pOSversion); 

    // always true ... 
    return (TRUE); 
} // GetTrueWindowsVersion 
2

Avrai bisogno di aggiungere un app.manifest alla vostra applicazione:

enter image description here

enter image description here

rimuovere il commento dalla seguente riga:

<!-- Windows 10 --> 
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> 
+0

La mia applicazione è console, quindi ho solo questo file App.config –

+1

È ancora possibile aggiungere un manifest a un'app console @PavelDurov – Nasreddine

+0

Sempre ottenendo 6.2 .... –

14

Nel mio scenario avevo bisogno la mia domanda per acquisire informazioni sul computer per possibili segnalazioni di bug e statistiche.

Non ho trovato le soluzioni in cui un manifest di applicazione doveva essere aggiunto soddisfacente. La maggior parte dei suggerimenti che ho trovato durante la ricerca su google ha suggerito proprio questo, sfortunatamente.

In questo caso, quando si utilizza un manifest, è necessario aggiungere manualmente ogni versione del sistema operativo affinché questa particolare versione del sistema operativo sia in grado di segnalarsi in fase di esecuzione.

In altre parole, questo diventa una condizione di competizione: un utente della mia app potrebbe utilizzare una versione della mia app che pre-data il sistema operativo in uso. Dovrei aggiornare l'app immediatamente quando una nuova versione del sistema operativo è stata lanciata da Microsoft.Dovrei anche costringere gli utenti ad aggiornare l'app nello stesso momento in cui hanno aggiornato il sistema operativo.

In altre parole, non molto fattibile.

Dopo aver sfogliato le opzioni ho trovato alcuni riferimenti (sorprendentemente pochi rispetto al manifest dell'app) che suggerivano invece l'uso delle ricerche di registro.

mio (abbattuto) ComputerInfo classe con solo WinMajorVersion, WinMinorVersion e IsServer proprietà si presenta così:

using Microsoft.Win32; 

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 
      { 
       using(var rk = Registry.LocalMachine.OpenSubKey(path)) 
       { 
        if (rk == null) return false; 
        value = rk.GetValue(key); 
        return value != null; 
       } 
      } 
      catch 
      { 
       return false; 
      } 
     } 
    } 
} 
+0

Questo è davvero fantastico, grazie! –

+0

'OpenSubKey' restituisce un'istanza' RegistryKey', che implementa 'IDisposable'. Essendo questo il caso, il suo utilizzo dovrebbe essere racchiuso in un costrutto 'using' per assicurare un corretto smaltimento deterministico. –

+0

@ JesseC.Slicer Penso che tu abbia ragione al riguardo. Mi adeguerò. Grazie. – Spiralis

1

Si può leggere da regsirty tramite il codice e fare un'azione specifica alle aspettative.

Di 'es:

chiave di registro si possono trovare qui:

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion e quindi cercare "ProductName"

È possibile aprire le informazioni del Registro di sistema dando regedit.exe Esegui (Windows + R)

var reg    =Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\WindowsNT\CurrentVersion"); 

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

     if (productName.StartsWith("Windows 10")) 
     { 
     } 
     else 
     { 
     } 
2
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuildNumber", string.Empty).ToString() 

stesso codice per tutti i sistemi operativi di XP fino a corrente 10,16,299 mila, su scenari non funziona correttamente da Windows 8

La proprietà OSVersion riporta il numero stessa versione (6.2.0.0) sia per Windows 8 e Windows 8.1 e lo stesso numero di versione maggiore e minore per Windows 10.

https://msdn.microsoft.com/library/system.environment.osversion.aspx