Langsam wird es unübersichtlich - Ermitteln der Windowsversion


Ja langsam wird es unübersichtlich. Was gibt es denn mittlerweile für Windowsversionen? Fangen wir mal an so aus dem Kopf, was ich so zusammen bringe:

Und da verließen sie ihn. Bei Windows Vista habe ich den Überblick verloren, was es da jetzt alles für Versionen gibt. Die Server Versionen habe ich übrigens mal alle außen vor gelassen, die kämen dann auch noch dazu. Soweit ist das ja noch nicht so schlimm, da Windows darauf achtet, dass die API abwärtskompatibel ist. Das geht so gar soweit, dass in den neuen Versionen Hacks (Siehe dazu Wikipedia "Hack" [1], letzte Definition) eingebaut werden. Einen interessanten Artikel hat dazu der Microsoft Programmierer Raymond Chen [2] verfasst: The long and sad story of the Shell Folders key [3]. Aber haarig wird es für einen Programmierer, wenn er in seinem Programm Funktionen benutzt, die nur ab einem bestimmten Betriebssystem zur Verfügung stehen. Dann muss diese Funktion dynamisch eingebunden werden, also "von Hand" aus der entsprechenden DLL geladen werden und vorher muss eine Versionsabfrage des Betriebssystems erfolgen. Und genau da fängt das Problem an. Wie man sich vorstellen kann, ist das nicht mehr so trivial. Allerdings kann man als Programmierer oftmals auf die Arbeit anderer Programmierer zurückgreifen und muss das Rad nicht neu erfinden. Für Delphi hat dies MagicAndre1981 mal getan und eine Unit1 geschrieben, die das für einem übernimmt. (Downloadlink siehe unten.)

Kleine Anekdote zu der API-Funktion GetVersion:

Die Funktion GetVersion [4] liefert einen DWORD Wert zurück, der die entsprechenden Informationen enthält. Ich habe mir nicht zugetraut diese Stelle des PSDK korrekt zu übersetzen, deswegen hier der englische original Text aus dem PSDK:

If the function succeeds, the return value includes the major and minor version numbers of the operating system in the low order word, and information about the operating system platform in the high order word. For all platforms, the low order word contains the version number of the operating system. The low-order byte of this word specifies the major version number, in hexadecimal notation. The high-order byte specifies the minor version (revision) number, in hexadecimal notation. To distinguish between operating system platforms, use the high order bit and the low order byte, as shown in the following table:

Ursprünglich, und das ist die Anekdote, sollte die Major Version im high-order Byte stehen und die Minor Version im low-order Byte des low word. Der Programmierer hat dies dummerweise aber verwechselt, so dass letztendlich die Major Version im low-order Byte gelandet ist. Die Tatsache, dass bereits viele Programmierer die Funktion benutzten, zwang Microsoft dazu die Funktion unverändert beizubehalten und die Dokumentation entsprechend anzupassen. Aufgrund der Verwirrung um GetVersion hat Microsoft die Windows-API um die neue Funktion GetVersionEx [5] ergänzt. (Quelle: "Microsoft Windows Programmierung für Experten" Seite 76, Jeffrey Richter, Microsoft Press, 4. Auflage, 2000)

Reicht es einem, ob das Programm auf einer bestimmten Betriebssystemversion läuft, reicht es übrigens, wenn man das gewünschte Ziel-System gegen VerifyVersionInfo [6] testet:

The VerifyVersionInfo function compares a set of operating system version requirements to the corresponding values for the currently running version of the system.

Delphi Beispiel:

type
  DWORDLONG = Int64;

type
  POSVersionInfoEx = ^TOSVersionInfoEx;
  TOSVersionInfoEx = packed record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: array[0..127] of AnsiChar;
    wServicePackMajor: Word;
    wServicePackMinor: Word;
    wSuiteMask: Word;
    wProductType: Byte;
    wReserved: Byte;
  end;

const
  VER_EQUAL         = 1; // The current value must be equal to the specified   value.
  VER_GREATER       = 2; // The current value must be greater than the speci-  fied value.
  VER_GREATER_EQUAL = 3; // The current value must be greater than or equal to the specified value.
  VER_LESS          = 4; // The current value must be less than the specified value.
  VER_LESS_EQUAL    = 5; // The current value must be less than or equal to the specified value.

  VER_AND           = 6; // All product suites specified in the wSuiteMask member must be present in the current system.
  VER_OR            = 7; // At least one of the specified product suites must be present in the current system.

  VER_BUILDNUMBER   = $0000004; // dwBuildNumber
  VER_MAJORVERSION  = $0000002; // dwMajorVersion If you are testing the major version, you must also test
                              // the minor version and the service pack version.
  VER_MINORVERSION  = $0000001; // dwMinorVersion
  VER_PLATFORMID    = $0000008; // dwPlatformId
  VER_SERVICEPACKMAJOR = $0000020; // wServicePackMajor
  VER_SERVICEPACKMINOR = $0000010; // wServicePackMinor
  VER_SUITENAME     = $0000040; // wSuiteMask
  VER_PRODUCT_TYPE  = $0000080; // wProductType

function VerifyVersionInfoW(var VersionInfo: TOSVersionInfoEx; TypeMask: DWORD; Conditionalmask: DWORDLONG): BOOL;
  stdcall; external 'kernel32.dll';
function VerSetConditionMask(dwlConditionMask: LONGLONG; TypeBitMask: DWORD; ConditionMask: Byte): LONGLONG; stdcall;
  external 'kernel32.dll';

function IsWinXPOrLater: BOOL;
var
  osvi              : TOSVersionInfoEx;
  ConditionMask     : DWORDLONG;
  op                : Integer;
begin
  op := VER_GREATER_EQUAL;

  ZeroMemory(@osvi, sizeof(TOSVersionInfoEx));
  osvi.dwOSVersionInfoSize := sizeof(TOSVersioNinfoEx);
  osvi.dwMajorVersion := 5;
  osvi.dwMinorVersion := 1;

  ConditionMask := 0;
  ConditionMask := VerSetConditionMask(ConditionMask, VER_MAJORVERSION, op);
  ConditionMask := VerSetConditionMask(ConditionMask, VER_MINORVERSION, op);

  result := VerifyVersionInfoW(osvi, VER_MAJORVERSION or VER_MINORVERSION, ConditionMask);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  res : BOOL;
begin
  res := IsWinXPOrLater;
  if res then
    ShowMessage('XP oder höher')
  else
    ShowMessage('Nicht Win XP oder höher');
end;

Anmerkungen:

  1. Auch wenn es im PSDK steht, unter Windows XP funktioniert die Erkennung des Sevicepacks nicht.
  2. Die Funktion VerifyVersionInfo steht erst ab Windows 2000 oder Windows XP zur Verfügung.

Downloads


GetWindowsVersion.zip Wednesday, 29-Dec-2010 23:45:34 CET 23K

Links

[1] http://de.wikipedia.org/wiki/Hack
[2] http://blogs.msdn.com/oldnewthing/default.aspx
[3] http://blogs.msdn.com/oldnewthing/archive/2003/11/03/55532.aspx
[4] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getversion.asp
[5] http://msdn2.microsoft.com/en-us/library/ms885648.aspx
[6] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/verifyversioninfo.asp
[7] http://www.michael-puff.de/Artikel/2006/files/GetWindowsVersion.zip


2010-12-29T23:44:47 +0100, mail+homepage[at]michael-puff.de