Получение основных, второстепенных и сборочных версий ОС для Windows 8.1 и выше в Delphi 2007
Я видел в нескольких вопросах / ответах о том, как определить версию ОС Win 8.1 и 10.0 с помощью VerifyVersionInfo (поскольку GetVersionEx больше не работает без проявления), но это позволяет мне только проверить, является ли ОС версией, которую вы передаете функция. Это не возвращает эту информацию мне. Например, в случае GetVersionEx он сообщает мне основные, вспомогательные и сборочные версии, но в случае VerifyVersionInfo мне необходимо задать вопрос: "Версия ОС 6.3 или выше?". или "Версия ОС 10.0 или выше?" поскольку GetVersionEx теперь возвращает 6,2 для версии ОС, даже если это на самом деле 6,3 или 10,0.
Это хорошо, потому что я могу легко добавить эту проверку в свой код, но теперь у меня нет возможности получить версию сборки, так как VerifyVersionInfo не сообщает мне об этом. Можно ли получить версию сборки каким-либо другим способом?
Вот что я делаю сейчас, чтобы определить, является ли ОС 8.1 или 10.0:
function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion, wServicePackMajor: Word): Boolean;
var
osvi: OSVersionInfoEX;
dwlConditionMask: Int64;
begin
FillChar(osvi, sizeof(osvi), 0);
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.dwMajorVersion := wMajorVersion;
osvi.dwMinorVersion := wMinorVersion;
osvi.wServicePackMajor := wServicePackMajor;
dwlConditionMask := VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
Result := VerifyVersionInfo(osvi, VER_MAJORVERSION or VER_MINORVERSION or VER_SERVICEPACKMAJOR, dwlConditionMask);
end;
function IsWindows8Point1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINBLUE), LOBYTE(WIN32_WINNT_WINBLUE), 0);
end;
function IsWindows10OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10), LOBYTE(WIN32_WINNT_WIN10), 0);
end;
function GetWinVersion: string;
var
osVerInfo: TOSVersionInfo;
majorVersion, minorVersion: Integer;
begin
Result := '?.?';
osVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo) ;
if GetVersionEx(osVerInfo) then
begin
minorVersion := osVerInfo.dwMinorVersion;
majorVersion := osVerInfo.dwMajorVersion;
if (majorVersion = 6) and (minorVersion = 2) then
begin
if IsWindows10OrGreater() then // 8.1+ does not report correct version.
Result := '10.0' // NOTE: NO BUILD NUMBER
else if IsWindows8Point1OrGreater() then
Result := '6.3'
else // This 6.2 is actually Win 8
result:=inttostr(majorVersion)+'.'+inttostr(minorVersion)+'.'+inttostr(osVerInfo.dwBuildNumber);
end
else
result:=inttostr(majorVersion)+'.'+inttostr(minorVersion)+'.'+inttostr(osVerInfo.dwBuildNumber);
end;
end;
РЕДАКТИРОВАТЬ: Как предложил Дэвид, решение было использовать WMI. Это работает с Win 8.1 и Win 10 и не требует наличия обновленного манифеста с каждой новой версией Windows.
function GetWinVersion8AndUp(): String;
const
WbemUser ='';
WbemPassword ='';
WbemComputer ='localhost';
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
Result := '';
try
try
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_OperatingSystem','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Result := Format('%s',[String(FWbemObject.Version)]);
FWbemObject:=Unassigned;
end;
except
end;
finally
end;
end;