检索Windows版本“1511”

最新版本的Windows 10(目前为Insider Preview)标记为:

版本1511(OS Build 10586.3)

查看“关于Windows”时(开始>运行> winver

使用适当显示的控制台应用程序,从System.Environment.OSVersion.Version返回的Windows版本是10.0.10586.0,它既不包含winver报告的版本的“1511”或“.3”组件。

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion下的注册表中似乎存在字符串,例如ReleaseId ,它将提供此信息,但这将依赖于实现细节而不是API合同。

简而言之,是否有一个(文档化的)API提供Windows 10版本,如winver和/或Help> About所示,Windows组件(如Notepad)可从.net应用程序调用?

以下是一些间接证据表明没有 API来获取“1511”字符串(除了从“ReleaseId”注册表值中读取它)。 这不是一个绝对的证据,它可能不是你想要的答案,但这就是我现在所拥有的。

使用sysinternals的ProcMon记录“winver”运行表明确实已经查询了注册表项,正如@SörenKuklau已经指出的那样。

 winver.exe RegQueryValue HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseID SUCCESS Type: REG_SZ, Length: 10, Data: 1511 

根据ProcMon的报告,RegQueryValueExW用于“ReleaseID”的调用堆栈如下所示。

  0 ntoskrnl.exe NtQueryInformationFile + 0x3d50 1 ntoskrnl.exe NtOpenThreadTokenEx + 0x258c 2 ntoskrnl.exe setjmpex + 0x3963 3 ntdll.dll ZwQueryValueKey + 0x14 4 KernelBase.dll MapPredefinedHandleInternal + 0x729 5 KernelBase.dll RegQueryValueExW + 0xed 6 SHCore.dll SHQueryValueExW + 0xdd 7 SHCore.dll SHQueryValueExW + 0x32 8 shell32.dll Ordinal897 + 0x86f 9 shell32.dll Ordinal897 + 0xb8b 10 shell32.dll Ordinal897 + 0x304 11 user32.dll IsDialogMessageW + 0x76e 12 user32.dll IsDialogMessageW + 0x941 13 user32.dll IsDialogMessageW + 0x866 14 user32.dll DispatchMessageW + 0x689 15 user32.dll SendMessageW + 0x395 16 user32.dll SetWindowLongPtrA + 0x979 17 user32.dll DialogBoxIndirectParamAorW + 0x18c 18 user32.dll DialogBoxIndirectParamAorW + 0x52 19 user32.dll DialogBoxParamW + 0x85 20 shell32.dll SHELL32_PifMgr_OpenProperties + 0x223d 21 shell32.dll ShellAboutW + 0x72 22 winver.exe winver.exe + 0x11d3 23 winver.exe winver.exe + 0x1516 24 kernel32.dll BaseThreadInitThunk + 0x22 25 ntdll.dll RtlUserThreadStart + 0x34 

因此,winver.exe从sh​​ell32.dll调用ShellAboutW,它会打开对话框并填充数据。 执行此操作时,它会读取“HKLM \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ ReleaseID”注册表值,该值返回“1511”。

确实在shell32.dll中找到了值“ReleaseID”作为硬编码字符串。 此外,唯一带有“ReleaseId”字符串的其他System32 DLL是SettingsHandlers_nt.dll和WSShared.dll – 但两者都没有被winver.exe加载,并且两者的“ReleaseID”大写不同(最后小写“d”,一件事)。 这强烈暗示:
(a)传递给RegQueryValueExW的字符串是shell32.dll中硬编码的字符串;
(b)其他MS代码具有类似的字符串硬编码,大概是因为没有API来获取它。

这仍然留下了可能由shell32.dll通过其他API公开相同的“1511”信息(或至少“ReleaseID”值名称)的可能性。 例如,有可能在调用栈中偏移8,9,10处的“Ordinal897”调用之一实际上可能是类似“GetWin10RelID(LPTSTR lpRellD,int nMaxChars)”的函数; 它也可能通过名称而不是序数导出,并在未来的SDK中记录。 但是,目前这些是由序数导出的匿名函数,没有文档,也不保证下次更新shell32.dll时它们甚至会保持相同的顺序。

FWIW,Process Monitor建议winver只是简单地查询ReleaseId 。 所以也许这就是“1511版”品牌的全部内容。

 23:59:30,6022870 winver.exe 7004 RegQueryValue HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseID SUCCESS Type: REG_SZ, Length: 10, Data: 1511 

当再次启动winver时,会立即反映将注册表值更改为随机值。 删除该值会使winver显示为空字符串。

所以,虽然没有很好地包装在API中并且可能不受支持,但这似乎是现在的诀窍:

 using (var hklmKey = Microsoft.Win32.Registry.LocalMachine) using (var subKey = hklmKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion")) { if (subKey != null) { string release = subKey.GetValue("ReleaseId") as string; if (release != null) retVal += " Version " + release; } }