delphi – 检查W10上的Windows版本

有人知道TOsversion.Name是否仍然适用于 Windows 10?

我有一个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?虽然注意到接受的答案是过时的.

作为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;

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...