38 votes

Comment détecter la vraie version de Windows

Je sais que je peux appeler la GetVersionEx fonction API Win32 pour récupérer la version de Windows. Dans la plupart des cas, la valeur de retour reflète la version de mon Windows, mais parfois ce n'est pas de la sorte.

Si un utilisateur exécute mon application sous la couche de compatibilité, puis GetVersionEx ne sera pas la vraie version, mais la version appliquée par la couche de compatibilité. Par exemple, si je suis sous Vista et exécuter mon programme "Windows NT 4" mode de compatibilité, GetVersionEx ne reviendra pas de la version 6.0, mais 4.0.

Est-il un moyen de contourner ce comportement et d'une vraie version de Windows?

29voto

gabr Points 20458

La meilleure approche, je sais, c'est pour vérifier si spécifique de l'API est exporté à partir de quelques DLL. Chaque nouvelle version de Windows ajoute de nouvelles fonctions et par la vérification de l'existence de ces fonctions, on peut dire que l'OS de l'application est en cours d'exécution sur. Par exemple, Vista exportations GetLocaleInfoEx de kernel32.dll alors que les précédents Windowses n'a pas.

Pour couper la longue histoire courte, voici une liste ne contenant que les exportations de kernel32.dll.

> *fonction: mise en œuvre dans* 
> GetLocaleInfoEx: Vista 
> GetLargePageMinimum: Vista, Server 2003 
GetDLLDirectory: Vista, Server 2003, XP SP1 
GetNativeSystemInfo: Vista, Server 2003, XP SP1, XP 
ReplaceFile: Vista, Server 2003, XP SP1, XP, 2000 
OpenThread: Vista, Server 2003, XP SP1, XP, 2000, ME 
GetThreadPriorityBoost: Vista, Server 2003, XP SP1, XP, 2000, NT 4 
IsDebuggerPresent: Vista, Server 2003, XP SP1, XP, 2000, ME, NT 4, 98 
GetDiskFreeSpaceEx: Vista, Server 2003, XP SP1, XP, 2000, ME, NT 4, 98, 95 OSR2 
ConnectNamedPipe: Vista, Server 2003, XP SP1, XP, 2000, NT 4, NT 3 
Bip: Vista, Server 2003, XP SP1, XP, 2000, ME, 98, 95 OSR2, 95 

L'écriture de la fonction afin de déterminer la vraie version de l'OS est simple; il vous suffit de procéder de la plus récente de l'OS à la plus ancienne et l'utilisation de GetProcAddress pour vérifier exporté Api. La mise en œuvre de ce dans n'importe quelle langue devrait être trivial.

Le code suivant dans Delphi a été extrait à partir de la libre DSiWin32 de la bibliothèque):

TDSiWindowsVersion = (wvUnknown, wvWin31, wvWin95, wvWin95OSR2, wvWin98,
  wvWin98SE, wvWinME, wvWin9x, wvWinNT3, wvWinNT4, wvWin2000, wvWinXP,
  wvWinNT, wvWinServer2003, wvWinVista);

function DSiGetWindowsVersion: TDSiWindowsVersion;
var
  versionInfo: TOSVersionInfo;
begin
  versionInfo.dwOSVersionInfoSize := SizeOf(versionInfo);
  GetVersionEx(versionInfo);
  Result := wvUnknown;
  case versionInfo.dwPlatformID of
    VER_PLATFORM_WIN32s: Result := wvWin31;
    VER_PLATFORM_WIN32_WINDOWS:
      case versionInfo.dwMinorVersion of
        0:
          if Trim(versionInfo.szCSDVersion[1]) = 'B' then
            Result := wvWin95OSR2
          else
            Result := wvWin95;
        10:
          if Trim(versionInfo.szCSDVersion[1]) = 'A' then
            Result := wvWin98SE
          else
            Result := wvWin98;
        90:
          if (versionInfo.dwBuildNumber = 73010104) then
             Result := wvWinME;
           else
             Result := wvWin9x;
      end; //case versionInfo.dwMinorVersion
    VER_PLATFORM_WIN32_NT:
      case versionInfo.dwMajorVersion of
        3: Result := wvWinNT3;
        4: Result := wvWinNT4;
        5:
          case versionInfo.dwMinorVersion of
            0: Result := wvWin2000;
            1: Result := wvWinXP;
            2: Result := wvWinServer2003;
            else Result := wvWinNT
          end; //case versionInfo.dwMinorVersion
        6: Result := wvWinVista;
      end; //case versionInfo.dwMajorVersion
    end; //versionInfo.dwPlatformID
end; { DSiGetWindowsVersion }

function DSiGetTrueWindowsVersion: TDSiWindowsVersion;

  function ExportsAPI(module: HMODULE; const apiName: string): boolean;
  begin
    Result := GetProcAddress(module, PChar(apiName)) <> nil;
  end; { ExportsAPI }

var
  hKernel32: HMODULE;

begin { DSiGetTrueWindowsVersion }
  hKernel32 := GetModuleHandle('kernel32');
  Win32Check(hKernel32 <> 0);
  if ExportsAPI(hKernel32, 'GetLocaleInfoEx') then
    Result := wvWinVista
  else if ExportsAPI(hKernel32, 'GetLargePageMinimum') then
    Result := wvWinServer2003
  else if ExportsAPI(hKernel32, 'GetNativeSystemInfo') then
    Result := wvWinXP
  else if ExportsAPI(hKernel32, 'ReplaceFile') then
    Result := wvWin2000
  else if ExportsAPI(hKernel32, 'OpenThread') then
    Result := wvWinME
  else if ExportsAPI(hKernel32, 'GetThreadPriorityBoost') then
    Result := wvWinNT4
  else if ExportsAPI(hKernel32, 'IsDebuggerPresent') then  //is also in NT4!
    Result := wvWin98
  else if ExportsAPI(hKernel32, 'GetDiskFreeSpaceEx') then  //is also in NT4!
    Result := wvWin95OSR2
  else if ExportsAPI(hKernel32, 'ConnectNamedPipe') then
    Result := wvWinNT3
  else if ExportsAPI(hKernel32, 'Beep') then
    Result := wvWin95
  else // we have no idea
    Result := DSiGetWindowsVersion;
end; { DSiGetTrueWindowsVersion }

--- mis à jour le 2009-10-09

Il s'avère qu'il devient très dur de faire un "sans-papiers", détection de système d'exploitation sur Vista SP1 et supérieur. Un regard sur les changements de l'API montre que tous les Windows 2008 fonctions sont également mis en œuvre dans Vista SP1 et que tous les Windows 7 fonctions sont également mis en œuvre dans Windows 2008 R2. Dommage :(

--- fin de la mise à jour

FWIW, c'est un problème que j'ai rencontré dans la pratique. Nous (la société où je travaille) ont un programme qui n'était pas vraiment avec Vista quand Vista est sorti (et quelques semaines après ...). Il n'a pas de travail en vertu de la couche de compatibilité soit. (Quelques problèmes DirectX. Ne demandez pas.)

Nous ne voulions pas trop-intelligent-pour-leur-propre-bonne les utilisateurs d'exécuter cette application sur Vista à tous les mode de compatibilité ou pas - j'ai donc dû trouver une solution (un mec plus intelligent que moi, m'a orienté dans la bonne direction; les trucs ci-dessus n'est pas de mon invention). Maintenant, je suis le poster, pour votre plaisir et pour aider tous les pauvres âmes qui auront à résoudre ce problème à l'avenir. Google, veuillez indice de cet article!

Si vous avez une meilleure solution (ou une mise à niveau et/ou de fixer, pour le mien), merci de poster une réponse ici ...

26voto

EBGreen Points 14478

Requête WMI:

 "Select * from Win32_OperatingSystem"
 

EDIT: En fait, mieux serait:

 "Select Version from Win32_OperatingSystem"
 

10voto

botismarius Points 1333

Que diriez-vous d'obtenir la version d'un fichier système?

Le meilleur fichier serait kernel32.dll, situé dans% WINDIR% \ System32 \ kernel32.dll.

Il existe des API pour obtenir la version du fichier. par exemple: j'utilise Windows XP -> "5.1.2600.5512 (xpsp.080413-2111)"

8voto

Scott Bilas Points 4958

Tous ceux qui sont arrivés à cette question devraient également lire cet article.

Vérification de version (il suffit de ne pas le faire)

Il est difficile de vérifier les versions. Assurez-vous que vous avez absolument besoin de le faire avant de copier le code collé à partir des réponses à cette question SO.

8voto

botismarius Points 1333

Une autre solution:

lisez l'entrée de registre suivante:

HLKM \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ CurrentVersion \ Nom du produit

ou d'autres clés de

HLKM \ LOGICIEL \ Microsoft \ Windows NT \ CurrentVersion \ CurrentVersion

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