Как определить истинную версию Windows?

Я знаю, что могу вызвать функцию Win32 API GetVersionEx для получения версии Windows. В большинстве случаев возвращаемое значение отражает версию моей Windows, но иногда это не так.

Если пользователь запускает мое приложение на уровне совместимости, GetVersionEx будет сообщать не реальную версию, а версию, обеспечиваемую уровнем совместимости. Например, если я запускаю Vista и выполняю свою программу в режиме совместимости с «Windows NT 4», GetVersionEx не вернет версию 6.0, а 4.0.

Есть ли способ обойти это поведение и получить настоящую версию Windows?


person gabr    schedule 11.09.2008    source источник
comment
Всем, кто пришел к этому вопросу, следует также прочитать эту статью. Проверка версии (только не делайте этого) Проверить версию сложно. Убедитесь, что вам абсолютно необходимо это сделать, прежде чем копировать вставку кода из ответов на этот вопрос SO.   -  person scobi    schedule 15.03.2011
comment
Хороший вопрос, я тоже хотел бы знать это, а также вернуть дополнительную информацию, такую ​​как Service Pack, Home / Professional / Ultimate edition и т. д.   -  person    schedule 15.05.2011
comment
Крейг; Проверьте мой ответ JCL. Он не обходит уровень совместимости, но он ДЕЙСТВИТЕЛЬНО говорит вам правду, если Windows не настроена так, чтобы вам лгать, и он может рассказать вам о выпусках и всем остальном.   -  person Warren P    schedule 14.11.2011
comment
ссылка archive.org на ссылку, предоставленную scobi: http://web.archive.org/web/20121013161123/http://windowsteamblog.com/windows/b/developers/archive/2009/08/05/version-verify-just-don-t-do-it.aspx   -  person dummzeuch    schedule 27.02.2017


Ответы (9)


Лучший подход, который я знаю, - это проверить, экспортируется ли конкретный API из какой-либо DLL. Каждая новая версия Windows добавляет новые функции, и, проверяя наличие этих функций, можно определить, на какой ОС работает приложение. Например, Vista экспортирует GetLocaleInfoEx из kernel32.dll в то время как предыдущие Windowses этого не делали.

Короче говоря, вот один такой список, содержащий только экспорт из kernel32.dll.

> *function: implemented in*  
> 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  
Beep:                    Vista, Server 2003, XP SP1, XP, 2000, ME,       98, 95 OSR2, 95  

Написать функцию для определения реальной версии ОС просто; просто перейдите от новейшей ОС к старой и используйте GetProcAddress для проверки экспортированных API. Реализация этого на любом языке должна быть тривиальной.

Следующий код в Delphi был извлечен из бесплатной библиотеки DSiWin32):

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 }

--- обновлено 2009-10-09

Оказывается, очень сложно выполнить "недокументированное" определение ОС в Vista SP1 и выше. Взгляд на изменения API показывает, что все Windows Функции 2008 также реализованы в Vista SP1, и все функции Windows 7 также реализованы в Windows 2008 R2. Очень плохо :(

--- конец обновления

FWIW, это проблема, с которой я столкнулся на практике. У нас (компании, в которой я работаю) есть программа, которая на самом деле не была готова к Vista, когда Vista была выпущена (и через несколько недель после этого ...). Он также не работал на уровне совместимости. (Некоторые проблемы с DirectX. Не спрашивайте.)

Мы вообще не хотели, чтобы слишком умные для себя хорошие пользователи запускали это приложение в Vista - в режиме совместимости или без - поэтому мне пришлось найти решение (парень умнее меня указал мне правильное направление; вышеперечисленное не моё детище). Сейчас выкладываю для вашего удовольствия и в помощь всем бедным душам, которым придется решать эту проблему в будущем. Google, проиндексируйте эту статью!

Если у вас есть лучшее решение (или обновление и / или исправление для меня), отправьте ответ здесь ...

person gabr    schedule 11.09.2008
comment
Я так хочу отредактировать этот пост, чтобы согласовать версии в первом разделе, но у меня недостаточно репутации. - person Brad Gilbert; 11.09.2008
comment
это должно быть довольно легко перевести на C #. - person Warren P; 31.03.2011
comment
Не уверен, что этой таблице можно доверять, AFAIK Beep существует на NT4 и ConnectNamedPipe на 9x - person Anders; 26.10.2011
comment
JEDI JCL также может определять версии сервера. - person Warren P; 12.11.2011
comment
@WarrenP, что это за функция JCL? - person gabr; 13.11.2011
comment
На самом деле в JCL есть много интересных вещей, связанных с проверкой версии Windows, поэтому я создал ответ на этот вопрос. - person Warren P; 14.11.2011
comment
JCL просто вызывает GetVersionEx и, следовательно, обманывается уровнем совместимости. - person gabr; 14.11.2011
comment
О, это важно отметить. Я посмотрю, как записать ошибку в JCL и добавить функцию GetRealWindowsVersion. В этом случае нам нужно будет использовать подход проверки API, подобный вашему, чтобы победить уровень совместимости. - person Warren P; 14.11.2011
comment
Примечание. Пакеты обновления Windows часто добавляют экспорт DLL с обратным переносом из более поздних версий. - person Sheng Jiang 蒋晟; 14.11.2011
comment
Помимо того, что это слишком сложный метод, он не поможет в будущих версиях Windows. - person oɔɯǝɹ; 29.04.2013
comment
Вот список, который вы можете использовать для поддержки более поздних ОС (Win 7 и т. Д.) geoffchappell .com / Studies / windows / win32 / kernel32 / api. - person osexpert; 08.08.2018

WMI-запрос:

"Select * from Win32_OperatingSystem"

РЕДАКТИРОВАТЬ: На самом деле лучше было бы:

"Select Version from Win32_OperatingSystem"

Вы можете реализовать это в Delphi так:

function OperatingSystemDisplayName: string;

  function GetWMIObject(const objectName: string): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;
    Moniker: IMoniker;
  begin
    OleCheck(CreateBindCtx(0, bindCtx));
    OleCheck(MkParseDisplayName(BindCtx, PChar(objectName), chEaten, Moniker));
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
  end;

  function VarToString(const Value: OleVariant): string;
  begin
    if VarIsStr(Value) then begin
      Result := Trim(Value);
    end else begin
      Result := '';
    end;
  end;

  function FullVersionString(const Item: OleVariant): string;
  var
    Caption, ServicePack, Version, Architecture: string;
  begin
    Caption := VarToString(Item.Caption);
    ServicePack := VarToString(Item.CSDVersion);
    Version := VarToString(Item.Version);
    Architecture := ArchitectureDisplayName(SystemArchitecture);
    Result := Caption;
    if ServicePack <> '' then begin
      Result := Result + ' ' + ServicePack;
    end;
    Result := Result + ', version ' + Version + ', ' + Architecture;
  end;

var
  objWMIService: OleVariant;
  colItems: OleVariant;
  Item: OleVariant;
  oEnum: IEnumvariant;
  iValue: LongWord;

begin
  Try
    objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
    colItems := objWMIService.ExecQuery('SELECT Caption, CSDVersion, Version FROM Win32_OperatingSystem', 'WQL', 0);
    oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
    if oEnum.Next(1, Item, iValue)=0 then begin
      Result := FullVersionString(Item);
      exit;
    end;
  Except
    // yes, I know this is nasty, but come what may I want to use the fallback code below should the WMI code fail
  End;

  (* Fallback, relies on the deprecated function GetVersionEx, reports erroneous values
     when manifest does not contain supportedOS matching the executing system *)
  Result := TOSVersion.ToString;
end;
person EBGreen    schedule 11.09.2008
comment
Одна проблема с WMI - он появился только в Windows 2000. Если вы знаете, что ваш код не будет работать на 9x или NT 3/4, то подход WMI подойдет. - person gabr; 11.09.2008
comment
У кого-нибудь еще работает 9х или NT? - person Camilo Martin; 16.12.2009
comment
WMI странный что ли? Select не работает на моем WMI, но "path Win32_OperatingSystem" работает. WMI - это сумасшедшая часть недостаточно задокументированной странности, или что? - person Warren P; 14.11.2011
comment
Похоже, вы получаете доступ к wmi через консольное приложение wmic. Когда я говорю WMI-запрос, я говорю о доступе к нему с помощью метода, поддерживающего язык запросов WQL (я понимаю, что это избыточно), чего нет в WMIC. Итак, чтобы ответить на ваш вопрос, некоторые части WMI не особенно хорошо документированы, потому что любой поставщик программного обеспечения может создавать классы в WMI в значительной степени, как и реестр, но части, которые создаются MS, и особенно части, связанные с ОС, являются на самом деле довольно хорошо задокументирован. - person EBGreen; 14.11.2011

Как насчет получения версии системного файла?

Лучшим файлом будет kernel32.dll, расположенный в% WINDIR% \ System32 \ kernel32.dll.

Есть API для получения версии файла. например: я использую Windows XP -> "5.1.2600.5512 (xpsp.080413-2111)"

person botismarius    schedule 11.09.2008
comment
Это подход, который рекомендует MSDN. - person Remy Lebeau; 29.06.2017

Другое решение:

прочтите следующую запись в реестре:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName

или другие ключи от

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
person botismarius    schedule 11.09.2008
comment
Это элегантно. Я рад, что продолжил читать, а не начал использовать опцию GetVersionEx. Сделайте это просто и красиво. - person Sam; 27.08.2010
comment
Чтение строк из реестра и их анализ - не лучшая идея, если это специально не задокументировано Microsoft. Вы уверены, что ProductName не переведен на другие языки? Вы уверены, что у вас есть все варианты названия продукта? Приведенный выше совет - это именно та вещь, которая заставляет команду App Compat в Microsoft вырвать волосы из головы. -1 - person scobi; 15.03.2011
comment
Что ж, тогда они должны предоставить API / официальное решение для получения этой информации. Скрытие информации редко бывает полезным. Как видите, каждое решение - это всего лишь обходной путь. - person botismarius; 16.03.2011
comment
Это конечно не элегантно - person David Heffernan; 31.07.2015
comment
Когда я читаю CurrentVersion на своем ноутбуке с Windows 8.1, на удивление он возвращается с 5.1 (номерами версий для Windows XP)! Это было использование более старого приложения Delphi 7 без манифеста, специально предназначенного для Windows 8.1. Используя regedit, определенно значение 6.3. Это говорит о том, что Windows должна намеренно перехватить чтение и применить какую-то прокладку совместимости. Единственный метод, который я нашел надежным, - это прочитать номера версий основной системной dll (я выбрал kernel32.dll) в соответствии с другим предложением от botismarius. Кажется немного взломанным, но это работает. - person AlainD; 26.02.2017
comment
Продолжая вышесказанное, ProductName возвращает Microsoft Windows XP, если фактическая запись - Windows 8.1! - person AlainD; 26.02.2017
comment
@AlainD кажется, что Microsoft доводит совместимость до крайности. - person botismarius; 26.02.2017

хранилище реальной версии в блоке информации о процессе PEB.

Пример для приложения Win32 (код Delphi)

unit RealWindowsVerUnit;

interface

uses
  Windows;

var
  //Real version Windows
  Win32MajorVersionReal: Integer;
  Win32MinorVersionReal: Integer;

implementation

type
  PPEB=^PEB;
  PEB = record
    InheritedAddressSpace: Boolean;
    ReadImageFileExecOptions: Boolean;
    BeingDebugged: Boolean;
    Spare: Boolean;
    Mutant: Cardinal;
    ImageBaseAddress: Pointer;
    LoaderData: Pointer;
    ProcessParameters: Pointer; //PRTL_USER_PROCESS_PARAMETERS;
    SubSystemData: Pointer;
    ProcessHeap: Pointer;
    FastPebLock: Pointer;
    FastPebLockRoutine: Pointer;
    FastPebUnlockRoutine: Pointer;
    EnvironmentUpdateCount: Cardinal;
    KernelCallbackTable: PPointer;
    EventLogSection: Pointer;
    EventLog: Pointer;
    FreeList: Pointer; //PPEB_FREE_BLOCK;
    TlsExpansionCounter: Cardinal;
    TlsBitmap: Pointer;
    TlsBitmapBits: array[0..1] of Cardinal;
    ReadOnlySharedMemoryBase: Pointer;
    ReadOnlySharedMemoryHeap: Pointer;
    ReadOnlyStaticServerData: PPointer;
    AnsiCodePageData: Pointer;
    OemCodePageData: Pointer;
    UnicodeCaseTableData: Pointer;
    NumberOfProcessors: Cardinal;
    NtGlobalFlag: Cardinal;
    Spare2: array[0..3] of Byte;
    CriticalSectionTimeout: LARGE_INTEGER;
    HeapSegmentReserve: Cardinal;
    HeapSegmentCommit: Cardinal;
    HeapDeCommitTotalFreeThreshold: Cardinal;
    HeapDeCommitFreeBlockThreshold: Cardinal;
    NumberOfHeaps: Cardinal;
    MaximumNumberOfHeaps: Cardinal;
    ProcessHeaps: Pointer;
    GdiSharedHandleTable: Pointer;
    ProcessStarterHelper: Pointer;
    GdiDCAttributeList: Pointer;
    LoaderLock: Pointer;
    OSMajorVersion: Cardinal;
    OSMinorVersion: Cardinal;
    OSBuildNumber: Cardinal;
    OSPlatformId: Cardinal;
    ImageSubSystem: Cardinal;
    ImageSubSystemMajorVersion: Cardinal;
    ImageSubSystemMinorVersion: Cardinal;
    GdiHandleBuffer: array [0..33] of Cardinal;
    PostProcessInitRoutine: Cardinal;
    TlsExpansionBitmap: Cardinal;
    TlsExpansionBitmapBits: array [0..127] of Byte;
    SessionId: Cardinal;
  end;

//Get PEB block current win32 process
function GetPDB: PPEB; stdcall;
asm
  MOV EAX, DWORD PTR FS:[30h]
end;

initialization
  //Detect true windows wersion
  Win32MajorVersionReal := GetPDB^.OSMajorVersion;
  Win32MinorVersionReal := GetPDB^.OSMinorVersion;
end.

person Victor Fedorenkov    schedule 21.06.2014
comment
Этот фальшивый stdcall делает весь фрагмент очень подозрительным. - person Free Consulting; 02.08.2015

Следующее работает для меня в Windows 10 без GUID Windows 10, указанного в манифесте приложения:

uses
  System.SysUtils, Winapi.Windows;

type
  NET_API_STATUS = DWORD;

  _SERVER_INFO_101 = record
    sv101_platform_id: DWORD;
    sv101_name: LPWSTR;
    sv101_version_major: DWORD;
    sv101_version_minor: DWORD;
    sv101_type: DWORD;
    sv101_comment: LPWSTR;
  end;
  SERVER_INFO_101 = _SERVER_INFO_101;
  PSERVER_INFO_101 = ^SERVER_INFO_101;
  LPSERVER_INFO_101 = PSERVER_INFO_101;

const
  MAJOR_VERSION_MASK = $0F;

function NetServerGetInfo(servername: LPWSTR; level: DWORD; var bufptr): NET_API_STATUS; stdcall; external 'Netapi32.dll';
function NetApiBufferFree(Buffer: LPVOID): NET_API_STATUS; stdcall; external 'Netapi32.dll';

type
  pfnRtlGetVersion = function(var RTL_OSVERSIONINFOEXW): LONG; stdcall;
var
  Buffer: PSERVER_INFO_101;
  ver: RTL_OSVERSIONINFOEXW;
  RtlGetVersion: pfnRtlGetVersion;
begin
  Buffer := nil;

  // Win32MajorVersion and Win32MinorVersion are populated from GetVersionEx()...
  ShowMessage(Format('GetVersionEx: %d.%d', [Win32MajorVersion, Win32MinorVersion])); // shows 6.2, as expected per GetVersionEx() documentation

  @RtlGetVersion := GetProcAddress(GetModuleHandle('ntdll.dll'), 'RtlGetVersion');
  if Assigned(RtlGetVersion) then
  begin
    ZeroMemory(@ver, SizeOf(ver));
    ver.dwOSVersionInfoSize := SizeOf(ver);

    if RtlGetVersion(ver) = 0 then
      ShowMessage(Format('RtlGetVersion: %d.%d', [ver.dwMajorVersion, ver.dwMinorVersion])); // shows 10.0
  end;

  if NetServerGetInfo(nil, 101, Buffer) = NO_ERROR then
  try
    ShowMessage(Format('NetServerGetInfo: %d.%d', [Buffer.sv101_version_major and MAJOR_VERSION_MASK, Buffer.sv101_version_minor])); // shows 10.0
  finally
    NetApiBufferFree(Buffer);
  end;
end.

Обновление: NetWkstaGetInfo(), вероятно, также будет работать, аналогично NetServerGetInfo (), но я еще не пробовал.

person Remy Lebeau    schedule 31.07.2015
comment
Приложение My Delphi 7 работает в Windows 8.1. Вызов RtlGetVersion из ntdll.dll возвращает 5.1 (номера версий для Windows XP). Это то же самое, что и числа, возвращенные из GetVersionEx. Еще не пробовал Netapi32 функцию. - person AlainD; 26.02.2017
comment
@remylebeau - Какой из этих 3 методов, по вашему мнению, более надежен для будущей совместимости (будущие версии Windows)? RtlGetVersion? - person Z80; 28.06.2017
comment
@AlainD отлично работает для меня и всех, кто его использует (многочисленные сообщения на SO показывают это). У вас случайно не работает EXE в режиме совместимости с XP? Без режима совместимости и отсутствия подходящего манифеста GetVersionEx будет сообщать номер версии Windows 8, а не XP. - person Remy Lebeau; 28.06.2017
comment
@RemyLebeau: Да, замечательно! Когда я отключил режим совместимости с XP, версия операционной системы вернется как Major=6 и Minor=2 (например, Windows 8). С тех пор пробовал это в Windows 10 с тем же результатом. - person AlainD; 07.07.2017

Примечание. Габр спрашивает о подходе, который может обойти ограничения GetVersionEx. Код JCL использует GetVersionEx и, таким образом, зависит от уровня совместимости. Эта информация предназначена только для людей, которым не нужно обходить уровень совместимости.

Используя Jedi JCL, вы можете добавить модуль JclSysInfo и вызвать функцию GetWindowsVersion. Он возвращает перечислимый тип TWindowsVersion.

В настоящее время JCL содержит все поставляемые версии Windows и изменяется каждый раз, когда Microsoft отправляет новую версию Windows в коробке:

  TWindowsVersion =
   (wvUnknown, wvWin95, wvWin95OSR2, wvWin98, wvWin98SE, wvWinME,
    wvWinNT31, wvWinNT35, wvWinNT351, wvWinNT4, wvWin2000, wvWinXP,
    wvWin2003, wvWinXP64, wvWin2003R2, wvWinVista, wvWinServer2008,
    wvWin7, wvWinServer2008R2);

Если вы хотите узнать, используете ли вы 64-битную Windows 7 вместо 32-битной, позвоните JclSysInfo.IsWindows64.

Обратите внимание, что JCL allso обрабатывает выпуски, такие как Pro, Ultimate и т. Д. Для этого вызова GetWindowsEdition, он возвращает одно из следующих:

TWindowsEdition =
   (weUnknown, weWinXPHome, weWinXPPro, weWinXPHomeN, weWinXPProN, weWinXPHomeK,
    weWinXPProK, weWinXPHomeKN, weWinXPProKN, weWinXPStarter, weWinXPMediaCenter,
    weWinXPTablet, weWinVistaStarter, weWinVistaHomeBasic, weWinVistaHomeBasicN,
    weWinVistaHomePremium, weWinVistaBusiness, weWinVistaBusinessN,
    weWinVistaEnterprise, weWinVistaUltimate, weWin7Starter, weWin7HomeBasic,
    weWin7HomePremium, weWin7Professional, weWin7Enterprise, weWin7Ultimate);

Для исторического интереса вы также можете проверить версию уровня NT с помощью функции NtProductType, она возвращает:

 TNtProductType =       (ptUnknown, ptWorkStation, ptServer, ptAdvancedServer,        
        ptPersonal, ptProfessional, ptDatacenterServer, 
        ptEnterprise, ptWebEdition);

Обратите внимание, что выше обнаружено "N выпусков". Это версия Windows для ЕС (Европы), созданная в соответствии с антимонопольными правилами ЕС. Это довольно хорошая градация обнаружения внутри JCL.

Вот пример функции, которая поможет вам обнаружить Vista и сделать что-то особенное в Vista.

function IsSupported:Boolean;
begin
  case GetWindowsVersion of
     wvVista:  result := false; 
    else
      result := true;
  end;
end;

Обратите внимание, что если вы хотите выполнить проверку «больше, чем», вам следует просто использовать другие методы. Также обратите внимание, что проверка версии часто может стать источником поломки в будущем. Обычно я предпочитаю предупреждать пользователей и продолжать, чтобы мой двоичный код не стал фактическим источником поломки в будущем.

Недавно я попытался установить приложение, и установщик проверил свободное место на моем диске и не смог установить, потому что у меня было более 2 гигабайт свободного места. 32-битное целое число со знаком в программе установки стало отрицательным, что нарушило работу программы установки. Мне пришлось установить его в виртуальную машину, чтобы заставить его работать. Добавление «умного кода» часто делает ваше приложение «глупее». Будьте осторожны.

Между прочим, я обнаружил, что из командной строки вы можете запустить WMIC.exe и ввести path Win32_OperatingSystem («Выбрать * из Win32_OperatingSystem» у меня не сработало). Возможно, в будущем JCL можно будет расширить для использования информации WMI.

person Warren P    schedule 14.11.2011

По сути, чтобы ответить на повторяющийся вопрос: Получение основной, дополнительной и сборки версий ОС для Windows 8.1 и более поздних версий в Delphi 2007

Начиная с W2K, вы можете использовать NetServerGetInfo. NetServerGetInfo возвращает правильную информацию о W7 и W8.1, не может проверить на W10 ..

function GetWinVersion: string;
var
  Buffer: PServerInfo101;
begin
  Buffer := nil;
  if NetServerGetInfo(nil, 101, Pointer(Buffer)) = NO_ERROR then
  try
     Result := <Build You Version String here>(
      Buffer.sv101_version_major,
      Buffer.sv101_version_minor,
      VER_PLATFORM_WIN32_NT // Save since minimum support begins in W2K
      );
  finally
    NetApiBufferFree(Buffer);
  end;
end;
person FredS    schedule 31.07.2015
comment
Было бы более полезно подождать, пока вы не сможете протестировать против Win10, поскольку эта тема активно обсуждалась в этом более позднем q: stackoverflow.com/ questions / 31753092 - person MartynA; 01.08.2015
comment
Я тестировал этот код в Windows 10 Preview (у меня еще нет окончательной версии). Без GUID Windows 10 в манифесте NetServerGetInfo() (а также RtlGetVersion() в ntdll.dll) сообщает версию как 10.0, тогда как GetVersionEx() сообщает версию как 6.2, как указано в документации. - person Remy Lebeau; 01.08.2015
comment
Полезно знать, мне нужно подождать, пока ошибка Something Happened не будет устранена :) - person FredS; 01.08.2015

Одно замечание об использовании NetServerGetInfo (), который все еще работает в Windows 10 (10240.th1_st1) ...

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370903%28v=vs.85%29.aspx.

sv101_version_major

Номер основной версии и тип сервера.

Номер основной версии операционной системы указывается в 4 младших разрядах. Тип сервера указывается в 4 старших разрядах. Битовая маска MAJOR_VERSION_MASK, определенная в заголовке Lmserver.h {0x0F}, должна использоваться приложением для получения основного номера версии от этого члена.

Другими словами, (sv101_version_major & MAJOR_VERSION_MASK).

person Ivry Gates    schedule 01.08.2015