在W10上检查Windows版本

时间:2015-09-03 14:46:09

标签: delphi operating-system windows-10 delphi-xe8

有没有人知道TOSVersion.Name是否仍适用于Windows 10?

我有一个vcl应用程序,它有一个表单show事件,可以获取操作系统的详细信息,并使用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,台式电脑,笔记本电脑和Surface Pro&#39 ;但不是安装在Windows 10上。

当我使用paserver进行调试时,TOSVersion.Name返回为:=' Windows 8'。 我做错了什么,或者我期望TOSVersion能够检测到Windows 10?没有例外被触发。在我有权访问的2台Windows 10计算机中,一条迁移路径来自Windows 8.1,另一条迁移路径来自Windows 7。

非常感谢

2 个答案:

答案 0 :(得分:11)

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

  1. 您使用的XE8 RTL早于Windows 10,因此不了解Windows 10。
  2. 您的可执行文件不会表现为支持Windows 10,因此TOSVersion所依赖的GetVersionEx将依赖于该版本。
  3. 我相信,XE8更新1会更改版本检测以使用不受此版本谎言影响的NetWkstaGetInfo。尽管对NetWkstaGetInfo的调用确实会泄漏内存,但这可能并不重要,因为它只被调用一次。

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

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

    • supportedOS选项添加到清单中,并包含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;
    

答案 1 :(得分:2)

您是否尝试过使用自定义清单?

我使用XE8并且在使用面向Windows 8.1和Windows 10的清单文件时,TOSVersion识别Windows 10没有任何问题。

我的自定义清单是为了使我的应用程序&#34; Windows 10&#34;察觉。

以下是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="MrTheV Dev"
    version="11.0.2804.9245"
    processorArchitecture="*"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="False"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
        <application> 
            <!-- Windows 10 --> 
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
        </application> 
    </compatibility>
</assembly>

我从这个链接得到了: https://msdn.microsoft.com/fr-fr/library/windows/desktop/dn481241(v=vs.85).aspx

Windows 10 1607上的TOSVersion.Tostring显示:

Windows (Version 10.0, Build 14393, 64-bit Edition)