在 W10 上检查 Windows 版本 [英] Checking Windows Version on W10

查看:34
本文介绍了在 W10 上检查 Windows 版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道 TOSVersion.Name 是否仍然适用于 Windows 10?

Does anyone know if TOSVersion.Name still works on Windows 10?

我有一个 vcl 应用程序,它有一个表单显示事件,该事件获取操作系统详细信息并使用来自 SysUtils 的 TOSVersion 记录将它们显示在 TMemo 框中.

I have a vcl application that has a form show event that gets the operating system details and displays them in a TMemo box using TOSVersion record from SysUtils.

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、台式电脑、笔记本电脑和 Surface Pro 上没有任何问题,但在 Windows 10 上安装时没有任何问题.

The code executes without any issues on XP (Yes we're still using it (hangs head in shame)), Vista, Windows 7, Windows 8.1, Desktop PC's, laptops and Surface Pro's but not when installed on Windows 10.

当我使用 paserver 进行调试时,TOSVersion.Name 返回为 := 'Windows 8'.我做错了什么还是我对 TOSVersion 检测 Windows 10 的期望过高?没有异常被触发.在我可以访问的 2 台 Windows 10 计算机中,一个迁移路径是从 Windows 8.1 迁移,而另一个迁移路径是从 Windows 7 迁移.

When I debug using paserver, TOSVersion.Name comes back as := 'Windows 8'. Am I doing something wrong or am I expecting too much for TOSVersion to detect Windows 10? No exception is being triggered. Of the 2 x Windows 10 machines I have access to, one migration path was from Windows 8.1, the other one however was from Windows 7.

非常感谢

推荐答案

有两件事会阻止您的代码返回正确的版本:

Two things stop your code from returning the correct version:

  1. 您使用的 XE8 RTL 早于 Windows 10,因此不了解 Windows 10.
  2. 您的可执行文件本身并不支持 Windows 10,因此 GetVersionEx 会对版本撒谎.

我相信 XE8 更新 1 碰巧将版本检测更改为使用不受此版本谎言约束的 NetWkstaGetInfo.虽然对 NetWkstaGetInfo 的调用确实会泄漏内存,但这可能并不重要,因为它只被调用一次.

It so happens that XE8 update 1, I believe, changes the version detection to use NetWkstaGetInfo which is not subject to this version lie. Although the call to NetWkstaGetInfo does leak memory, but that's probably not important since it is only called once.

与此主题相关的一些链接:

Some links relating to this subject:

如果您绝对必须向用户报告版本,那么您有多种选择:

If you absolutely must report the version to the user, then you have a variety of options:

  • supportedOS 选项添加到您的清单,并包含适用于 Windows 10 的 GUID.这可以防止 GetVersionEx 撒谎.然后使用 TOSVersion 的修改版本或其他方式来获取版本.
  • 使用 WMI 查询.
  • 调用NetServerGetInfo.
  • 调用NetWkstaGetInfo.
  • 调用RtlGetVersion.
  • Add the supportedOS option to your manifest and include the GUID for Windows 10. That stops GetVersionEx from lying. Then use a modified version of TOSVersion, or some other means, to obtain the version.
  • Use a WMI query.
  • Call NetServerGetInfo.
  • Call NetWkstaGetInfo.
  • Call RtlGetVersion.

这个问题的更多细节:如何检测真正的 Windows 版本?尽管请注意,那里接受的答案已过时.

More details in this question: How to detect true Windows version? Although note that the accepted answer there is out-of-date.

作为 WMI 方法的示例,您可以使用以下代码:

As an example of the WMI approach, you could use this code:

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;

这篇关于在 W10 上检查 Windows 版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆