Get the version of Windows at runtime

How can I get the version of Windows at runtime?

Use the WinAPI call to GetVersion. GetVersion returns 3.1 for Win 3.1, 3.11, WfW 3.11 and Win NTwhen called from a 16-bit app in any of these environments, and 3.95 for Win95.

Also from a 16-bit app, you can detect NT with the following (thanks to Peter Below):

  Const WF_WINNT = $4000;
  IsNT := (GetWinFlags and WF_WINNT) <> 0;

Unfortunately, the above doesn't work for the 32-bit programs that you will be compiling in Delphi 2.0. For that, you have to use the new Win32 API call: GetVersionEx. GetVersionEx supercedes GetVersion for all 32-bit applications. Instead of returning a numeric value as in GetVersion, it fills the contents of a variable of a record of type TOSVersionInfo, from which you can gather much more detailed information about the Windows environment in which your program is running. Let's look at the various record elements of TOSVersionInfo:

The Window.PAS file lists TOSVersionInfo as the following:

  TOSVersionInfoA = record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: array[0..127] of AnsiChar; { Maintenance string for PSS
usage }
  TOSVersionInfo := TOSVersionInfoA;

Notice that TOSVersionInfo is actually an assignment from another type, TOSVersionInfoA. There are actually two different version info types: TOSVersionInfoA and TOSVersionInfoW. The only difference between the two is in the szCSDVersion element. For the 'A' version info type, it's of an array of AnsiChar. The 'W' version info type is of an array of WideChar.

For our purposes, we're only interested in the 'A' type. Look at the table below to see what various elements represent:

Elements of TOSVersionInfo
Element Type Description
dwOSVersionInfoSize DWORD This element carries the memory size of the TOSVersionInfo variable. In fact, to use GetVersionEx, you have to initialize this element to SizeOf(TOSVersionInfo). Otherwise, the function will return a failure.
dwMajorVersion DWORD This is the major release number for Windows, which is on the left-hand side of the period. For example, it would be the '3' for version 3.51
dwMinorVersion DWORD This is the portion of the release number on the right-hand side of the period. It would be the '51' in 3.51
dwBuildNumber DWORD Build numbers aren't readily apparent in Windows 3.1x versions, but show up often in Win95 and NT. Just a finer level of versioning.
dwPlatformId DWORD This parameter tells you what level of Win32(s) your system is. It returns one of the three following constants:



For most folks, this will probably be the element they'll use the most.

szCSDVersion array[0..127] of AnsiChar This parameter provides additional textual information about the version. For NT, it would list the Service Pack level installed.

How you employ this is entirely up to you. If you're writing apps that need to know what version of Windows they're running under, a function like this is essential. For example, let's say you write a Winsock application under Windows 95. With that type of app, you can address either a 16-bit Winsock DLL or a 32-bit Winsock. A good example of this is CompuServe Information Manager for Windows. It comes with its own 16-bit Winsock, but can also use WinNT's native WSOCK32.DLL as its winsock. It's obviously a matter of looking under the hood of Windows to decide what to use.

I have source code to share with you. This is a simple unit I built to display in string format all the elements of the TOSVersionInfo type. If you want to build the form to use this code, just follow these simple steps:

  1. Start a new project
  2. Drop the following on the form: six TEdits, six TLabels and a TButton.
  3. Then insert the code below for the TButton's OnClick event, and that's it!

The TLabels should be named dwOSVersionInfoSize, dwMajorVersion, dwMinorVersion, dwBuildNumber, dwPlatformId, and szCSDVersion, respectively.

unit u;


  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    procedure Button1Click(Sender: TObject);
    { Private declarations }
    { Public declarations }

  Form1: TForm1;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
  str     : String;
  I       : Word;
  verInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
  if GetVersionEx(verInfo) then begin
    Edit1.Text := IntToStr(verInfo.dwOSVersionInfoSize);
    Edit2.Text := IntToStr(verInfo.dwMajorVersion);
    Edit3.Text := IntToStr(verInfo.dwMinorVersion);
    Edit4.Text := IntToStr(verInfo.dwBuildNumber);
    case verInfo.dwPlatformId of
      VER_PLATFORM_WIN32s         : Edit5.Text := 'Win16 running Win32s';
      VER_PLATFORM_WIN32_WINDOWS  : Edit5.Text := 'Win32 Windows, probably Win95';
      VER_PLATFORM_WIN32_NT       : Edit5.Text := 'WinNT, full 32-bit';

    str := '';

    for I := 0 to 127 do
      str := str + verInfo.szCSDVersion[I];

    Edit6.Text := str;


The program above doesn't have tangible uses other than getting information, but it's a good way to dig into the TOSVersionInfo record. You can even use GetVersionEx on a splash screen to add a little "intelligence" to your apps.