11

昨天发布的 Windows 11 几乎在所有地方都报告为 Windows 10.0 -RtlGetVersion说是 10.0,如果你问VerifyVersionInfo你是 11.0 还是更高版本,它说不是。

似乎没有新的 GUID 可以像 Windows 7、8、8.1 和 10 那样插入 app.manifest 来说“嘿,我支持 Windows 11”。

目前我依靠HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName告诉我当前的 Windows 版本是什么,但在我升级的机器上,它仍然显示“Windows 10 Enterprise”,而不是“Windows 11 Enterprise”。

注册表中似乎只有一个地方包含文本“Windows 11”,那就是 BCD 部分(启动配置),它也可以重命名,所以我不想碰它。

到目前为止,我只确定了几种方法来判断我是否在 Windows 11 上运行:

  1. 调用 WMI 来查询 Win32_OperatingSystem 并检查 Name 属性,它只是说“Windows 11”。这是不完整的(它不包括诸如“企业”之类的 SKU),并且 WMI 相对较慢且略显脆弱,因此对于我的用例来说,这不是一个可接受的解决方案。

  2. 检查内部版本号是否高于 21996(测试版)或 22000(首次公开发布)。如上所述,这不包括 SKU,并且需要一些手动的 jiggery-pokery 才能构建完整的字符串。

  3. 运行sysinfo并解析输出。这很慢,而且可能很脆弱(我没有检查过,但输出可能被本地化为不同的语言)。

  4. winver知道,但它是一个 GUI 应用程序,所以我不能完全以编程方式查询它。

是否有人对如何以高性能和完整的方式从我的操作系统中获取字符串“Windows 11 Enterprise”(或“Windows 11 Pro”等,视情况而定)有任何其他想法?WMI、sysinfo 和 winver 从哪里获得它?

我需要从 .NET 库中执行此操作,但 P/Invokes/本机函数调用是可接受的解决方案。

4

4 回答 4

5

把它留在这里,以便我以后可以找到它:

似乎 Windows 本身(例如 winver)从 Windows 品牌中获取此信息 - 特别是从%WinDir%\Branding\Basebrd\en-US\basebrd.dll.mui.

要访问这个,可以使用%WinDir%\System32\winbrand.dll. 具体来说,BrandingFormatString接受宽字符串 (LPW[C]STR) 并返回宽字符串的函数。

例如BrandingFormatString("%WINDOWS_LONG%")返回"Windows 11 Pro"我的家用电脑。

我不知道结果字符串的生命周期语义,即是否/何时/如何释放它。

以下代码用作功能性概念验证 (C# 9.0):

using System;
using System.Runtime.InteropServices;

[DllImport("winbrand.dll", CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern string BrandingFormatString(string format);

Console.WriteLine(BrandingFormatString("Hello World from %WINDOWS_LONG%!"));

于 2021-10-06T08:57:40.357 回答
2

tldr - 在注册表中使用和EditionID似乎是确定 Win10 与 Win11 和软件“版本”的可靠方法。在 Windows 10 Pro 和 Windows 11 Pro 上是“Professional”,并告诉你是 10 还是 11。CurrentBuildCurrentVersionEditionIDCurrentBuild >= ~22000

注册表值的集合HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion揭示了微软缺乏计划的感觉。有ReleaseId, 这是一个随每个 Windows 10 版本(例如 、190319092004...)而变化的数字,直到它在 Windows 10 20H2 的最后一次更改中更改为2009。同时,DisplayVersion被添加,并被设置为20H2

随后Windows 10 21H1发布,ReleaseId莫名停留在2009.

当前的 Windows 10 和 Windows 11 版本可以具有相同的DisplayVersion(例如,21H2当 Windows 10 21H2 即将发布时)和ProductName(例如,Windows 10 Pro)这一事实确实令人头疼。(感谢@yaakov 发现我说是 21H1 的错误。)

于 2021-10-07T19:07:26.837 回答
1

我为桌面管理员创建了一个远程支持工具(参见http://www.appslife-rdt.appspot.com) 在 VB.Dot.Net 中,我调用了 WMI 空间 Win32_OperatingSystem 并取回了“名称”值。然后需要将其拆分以获得您需要的第一个对象。IE

Dim query2 As New SelectQuery("SELECT * FROM Win32_OperatingSystem")
Dim searcher2 As New ManagementObjectSearcher(objManagementScope2, query2, QueryOptions)
        For Each mo As ManagementObject In searcher2.[Get]()
                           OSname = mo("Name")
        Next

        Dim array1 As Array = Nothing
        array1 = Split(OSname, "|")
        OSname = array1(0).ToString

OSname 然后为您提供所需的“Windows 11 Pro”或“Windows XP Professional”。

如果需要,我还会从注册表中获取带有最新补丁更新信息的 OSVersion,如下所示...

这适用于客户端版本 10/11:-

.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Client.OS.rs2.amd64") .SetPropertyValue("sValueName", "Version")

这适用于 2019 年服务器版本:-

.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Server.OS.amd64") .SetPropertyValue("sValueName", "Version")

希望这是有帮助的。

于 2021-11-18T19:19:36.113 回答
0

以下代码已在 Windows XP、7、10、11 上进行了测试。它适用于 32 位和 64 位操作系统。它适用于 32 位和 64 位应用程序。

将生成以下字符串:

  • “Microsoft Windows XP,Build 2600,32 位”
  • “Windows 7 Ultimate,Build 7601,64 位”
  • “Windows 10 企业版 LTSC 2019,版本 1809,内部版本 17763,64 位”
  • “Windows 10 专业版,版本 1909,内部版本 18362,64 位”
  • “Windows 11 专业版,版本 21H2,内部版本 22000,64 位”

将代码放入静态构造函数中,使其只执行一次并将版本写入静态变量。

static String ms_OperatingSystem;

static Constructor()
{
    try
    {
        String s_KernelPath = Path.Combine(Environment.SystemDirectory,"Kernel32.dll");
        FileVersionInfo k_Kernel = FileVersionInfo.GetVersionInfo(s_KernelPath);

        // on 32 bit Windows this will read the 32 bit hive instead
        using (RegistryKey i_HKLM = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
        {
            using (RegistryKey i_RegVer = i_HKLM.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion", false))
            {
                // Kernel32.dll on Windows 11 has Product Version 10.0.22000.120
                if (k_Kernel.ProductMajorPart == 10 && k_Kernel.ProductBuildPart >= 22000)
                {
                    ms_OperatingSystem = "Windows 11";

                    Object o_Edition = i_RegVer.GetValue("EditionID"); // "Professional"
                    if (o_Edition is String)
                        ms_OperatingSystem += " " + o_Edition;
                }
                else
                {
                    // "Microsoft Windows XP"
                    // "Windows 7 Ultimate"
                    // "Windows 10 Pro"  (same string on Windows 11. Microsoft SUCKS!)
                    ms_OperatingSystem = (String)i_RegVer.GetValue("ProductName");
                }

                // See: https://en.wikipedia.org/wiki/Windows_10_version_history
                // Windows 10 older releases --> "2009" (invalid if DisplayVersion exists)
                Object o_ReleaseID = i_RegVer.GetValue("ReleaseId");

                // Windows 10 latest release --> "21H1"
                // Windows 11 first  release --> "21H2"
                Object o_DispVer = i_RegVer.GetValue("DisplayVersion");

                // Use ReleaseID ONLY if DisplayVersion does not exist in registry!
                     if (o_DispVer   is String) ms_OperatingSystem += ", Version " + o_DispVer;
                else if (o_ReleaseID is String) ms_OperatingSystem += ", Version " + o_ReleaseID;

                ms_OperatingSystem += ", Build " + k_Kernel.ProductBuildPart;

                if (Environment.Is64BitOperatingSystem) ms_OperatingSystem += ", 64 bit";
                else                                    ms_OperatingSystem += ", 32 bit";
            }
        }
     }
     catch (Exception Ex)
     {
        ms_OperatingSystem = Ex.Message;
     }
}
于 2021-12-23T00:38:07.080 回答