sysinfo
sysinfo copied to clipboard
Windows 11 versioning incorrect
When on Windows 11, functions such as long_os_version are returning what they would on Windows 10. It seems that the crate is pulling these values from registry (SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion) and the registry values are not updated when upgrading from W10 to W11.
While I would consider it outside of the scope of the crate to fix strange Windows versioning quirks, according to a post on the Microsoft forums about this issue, they were told by a Windows dev that quering registry values for versioning was not the 'proper' way to get versioning info and the revelvant API calls should be used instead.
I can understand if you do not want to deal with this behaviour and this will never be fixed, however I thought I would report the issue in case you were not aware of it and for anyone looking for information on why their versioning info seemed to be incorrect when running Windows 11
No, it should work as expected. The problem being that I don't have a Windows 11. If someone with a Windows 11 could fix this issue, this would be very appreciated. :)
I have an upgraded Win11 machine. I've tried all the WinAPIs including GetVersionExA() and GetProductInfo() and none of them work correctly - actually they produce just wrong and incorrect versions - for instance GetProductInfo which is supposed to be the best way, says my machine is "Windows 10 Enterprise Evaluation" which is nonsense - it is Win11 Pro. The only way I can see to do this correctly is to look at the build number (22000 and > for Win11) which seems to return correctly. I'm happy to create a pull request to hashmap a table of build numbers if you like?
That would be very welcome!
I looked into this and came to the conclusion that checking the version number is good enough. There are definately APIs that report the correct version somewhere. This powershell line does Get-WmiObject -Class Win32_OperatingSystem | Format-List -Property Caption report Windows 11, however I'm still trying to find the API this calls that does actually report the correct version
I would be interested to see if there a definite WinAPI call that works i.e. I want to see "11" or "10" or "8.1" come back. My reading came to the conclusion that GetVersionExA() is deprecated and GetProductInfo should be the call. However, both are not suitable just to retrieve a version number and need post processing with logic and even that is more complicated and error prone. The build or kernel number is much more accurate and is documented in tables to match the major version number. More info here... https://docs.microsoft.com/en-us/windows/win32/sysinfo/version-helper-apis and here.. https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo
We can add a match on the builder/kernel number. But that will mean that when a new Windows version is released, we will need to update the code. It's fine by me but something to remember. :)
The build numbers are in ranges for the the major OS version. So we would only need to update the code when Windows 12 gets released. I can't think of another way to do this accurately unless Microsoft release an API that actually works. I'm certainly not happy it's come to this hacky solution.
It's fine. Anyone interested into sending a PR to do it?
Just finishing another Rust project, I'm a novice but might be interested in creating a PR for you.
No hurry then. Take your time. :)
Hello! I researched several sources and came to the same conclusion. The easiest way to distinguish windows 11 from 10 is by looking into "CurrentBuildNumber, as mentioned above. Windows 11's build number starts from "22000", and 10's is from "10240" up to "19044" at present.
I made some simple changes and confirmed it goes as expected.
static WINDOWS_ELEVEN_BUILD_NUMBER: u32 = 22000;
impl System {
fn is_windows_eleven(&self) -> bool {
WINDOWS_ELEVEN_BUILD_NUMBER
>= self
.kernel_version()
.unwrap_or_default()
.parse()
.unwrap_or(0)
}
}
fn long_os_version(&self) -> Option<String> {
if self.is_windows_eleven() {
return get_reg_string_value(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
"ProductName",
)
.map(|product_name| product_name.replace("10", "11"));
}
get_reg_string_value(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
"ProductName",
)
}
let mut sys = System::new_all();
sys.refresh_all();
// Some("Windows")
println!("{:?}", sys.name());
// Some("Windows 11 Home")
println!("{:?}", sys.long_os_version());
// Some("11 (22000)")
println!("{:?}", sys.os_version());
@k0i Want to open a pull request with these changes? :)
Thank you for your time GuillaumeGomez ! I'll give it a try!
Thanks for this fix