我有一个vcl应用程序,它具有一个表单显示事件,可以获取操作系统的详细信息,并使用SysUtils中的TOSVersion记录将它们显示在一个TMemo框中.
with mmoOSInfo.Lines do begin Clear; Add(TOSVersion.ToString); Add(''); Add('Architecture: ' + OSArchitectureToStr(TOSVersion.Architecture)); Add('Platform: ' + OSPlatformToStr(TOSVersion.Platform) + IntToStr(PlatformFromPointer)); Add('Build: ' + IntToStr(TOSVersion.Build)); Add('Major: ' + IntToStr(TOSVersion.Major)); Add('Minor: ' + IntToStr(TOSVersion.Minor)); Add('Name: ' + TOSVersion.Name); Add('Service Pack - Major: ' + IntToStr(TOSVersion.ServicePackMajor)); Add('Service Pack - Minor: ' + IntToStr(TOSVersion.ServicePackMinor)); end;
代码在XP上执行没有任何问题(是的,我们仍然使用它(羞耻的头)),Vista,Windows 7,Windows 8.1,台式PC,笔记本电脑和Surface Pro,而不是安装在Windows 10上.
当我使用paserver调试时,TOSVersion.Name返回为:=’Windows 8′.
我做错了什么,或者我期待太多的TOSVersion来检测Windows 10?没有例外被触发.在我可以访问的2台Windows 10机器中,一个迁移路径来自Windows 8.1,另一个来自Windows 7.
非常感谢
解决方法
>您使用的XE8 RTL之前的Windows 10等都不了解Windows 10.
>您的可执行文件不表现为支持Windows 10,因此,TOSVersion依赖的GetVersionEx
将会涉及版本.
这样XE8更新1就会发生,我相信更改版本检测使用NetWkstaGetInfo不受此版本的限制.虽然调用NetWkstaGetInfo确实泄漏内存,但这可能不重要,因为它只被调用一次.
与此相关的一些链接:
> Operating system version changes in Windows 8.1 and Windows Server 2012 R2
> Why Windows 8.1 Sometimes Tells You It Is Windows 8.0
> GetVersionEx
> Targeting your application for Windows
>还有很多更多….
如果您绝对必须向用户报告版本,那么您有各种选项:
>将supportsOS选项添加到您的清单,并包含Windows 10的GUID.这样可以让GetVersionEx从撒谎.然后使用TOSVersion的修改版本或其他方法来获取版本.
>使用WMI查询.
>调用NetServerGetInfo.
>调用NetWkstaGetInfo.
>调用RtlGetVersion.
这个问题的更多细节:How to detect true Windows version?虽然注意到接受的答案是过时的.
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;