Ответ 1
Две вещи не позволяют вашему коду вернуть правильную версию:
- XE8 RTL, который вы используете в предшествующем Windows 10 и поэтому не знает Windows 10.
- Ваш исполняемый файл не проявляет себя как поддерживающий Windows 10, поэтому
GetVersionEx
, на который полагаетсяTOSVersion
, будет лгать версии.
Так получилось, что обновление XE8 1, я считаю, изменяет обнаружение версии на использование NetWkstaGetInfo
, которое не подпадает под эту версию. Хотя вызов NetWkstaGetInfo
вызывает утечку памяти, но это, вероятно, не важно, поскольку он вызывается только один раз.
Некоторые ссылки, относящиеся к этой теме:
- Изменения версии операционной системы в Windows 8.1 и Windows Server 2012 R2
- Почему Windows 8.1 иногда говорит вам, что это Windows 8.0
-
GetVersionEx
- Ориентация приложения на Windows
- И многое другое....
Если вам абсолютно необходимо сообщить о версии пользователю, у вас есть множество вариантов:
- Добавьте параметр
supportedOS
в ваш манифест и включите GUID для Windows 10. Это прекратит использованиеGetVersionEx
. Затем используйте модифицированную версиюTOSVersion
или некоторые другие средства для получения версии. - Используйте запрос WMI.
- Вызов
NetServerGetInfo
. - Вызов
NetWkstaGetInfo
. - Вызов
RtlGetVersion
.
Подробнее в этом вопросе: Как определить истинную версию Windows? Хотя обратите внимание, что принятый ответ устарел.
В качестве примера подхода WMI вы можете использовать этот код:
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;