昨天发布的Windows 11几乎到处都是Windows10.0,RtlGetVersion
说10.0,如果你问VerifyVersionInfo
你是不是11.0或更高,它会说不。
似乎没有新的GUID可以插入app.manifest说“嗨,我支持Windows 11”,就像Windows 7、8、8.1和10那样。
目前,我依赖HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName
来告诉我当前版本的Windows是什么,但是在我升级的机器上,它仍然是“Windows10Enterprise”,而不是“Windows11Enterprise”。
注册表中似乎只有一个包含文本"Windows 11“的位置,那就是BCD部分(引导配置),它也可以重命名,所以我不想碰它。
到目前为止,我只确定了几种方法来判断我是否运行在Windows 11上:
。
sysinfo
并解析输出。这很慢,而且可能很脆弱(我还没有检查,但输出可能被本地化为不同的语言)。winver
知道,但它是一个GUI应用程序,所以我不能确切地查询它,programmatically.有没有人有其他的想法,如何使字符串"Windows 11 Enterprise“(或"Windows 11 Pro”等,视情况而定)从我的操作系统以一种性能和完整的方式?WMI,sysinfo和winver从哪里得到的?
我需要通过.NET库来实现这一点,但是P/调用/本机函数调用是可以接受的解决方案。
发布于 2021-10-06 00:57:40
把这个留在这里好让我以后能找到它:
Windows本身(例如winver)似乎是从Windows品牌--特别是从%WinDir%\Branding\Basebrd\en-US\basebrd.dll.mui
中的资源表--获得这些信息的。
要访问这个,可以使用%WinDir%\System32\winbrand.dll
中的私有API。具体来说,函数BrandingFormatString
接受一个宽字符串(LPWCSTR)并返回一个宽字符串。
例如,BrandingFormatString("%WINDOWS_LONG%")
在我家的PC上返回"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-07 11:07:26
tldr -在注册表中使用EditionID
和来自CurrentVersion
的CurrentBuild
似乎是确定Win10与Win11和软件“版本”的可靠方法。EditionID
在Windows10Pro和Windows11Pro上是“专业”的,CurrentBuild >= ~22000
告诉您它是10还是11。
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
中的注册表值集合揭示了微软方面缺乏计划的感觉。有ReleaseId
,它是随着每个Windows 10版本而变化的数字(例如,1903
、1909
、2004
、.)直到最后一次更改Windows1020H2,在那里它更改为2009
。同时,添加了DisplayVersion
,并将其设置为20H2
。
然后Windows1021H1发布,ReleaseId
莫名其妙地停留在2009
上。
当前的Windows 10和Windows 11版本都可以具有相同的DisplayVersion
(例如,在Windows1021H2即将发布时的21H2
)和ProductName
(例如,Windows 10 Pro
)。(谢谢@yaakov抓住我说的是21H1的错误。)
发布于 2021-12-22 16:38:07
下面的代码已经在Windows、7、10、11上进行了测试。它可以在32位和64位操作系统上工作。它在32位和64位应用程序中工作。
将生成以下字符串:
H 210F 211
>将代码放入静态构造函数,使其只执行一次,并将版本写入静态变量。
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;
}
}
https://stackoverflow.com/questions/69460588
复制