I have a program that reports and/or detects the Windows OS version. It uses GetVersionEx, but Microsoft intentionally broke this API in Windows 8.1 and later to return incorrect version information. (Apparently proper version checking is just too hard for the masses to get right, but that's a rant for another topic.)
I know that I can add a manifest to work around this particular problem, but my question is about "future-proofing" the program.
If a future user runs the program on a newer OS than Windows 10, will GetVersionEx work correctly and report the "real" OS version, even if the program's manifest doesn't include that version's GUID?
Or am I doomed to continually add new GUIDs to the manifest every time a new OS version is released?
If a future user runs the program on a newer OS than Windows 10, will GetVersionEx work correctly and report the "real" OS version, even if the program's manifest doesn't include that version's GUID?
NO, and this is documented behavior:
With the release of Windows 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version. The value returned by the GetVersionEx function now depends on how the application is manifested.
Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10, refer to Targeting your application for Windows.
Or am I doomed to continually add new GUIDs to the manifest every time a new OS version is released?
Sadly, YES. The point of version manifestation is to explicitly report the OS version(s) that your app is known to be compatible with. Obviously you can't know ahead of time if it is compatible with future versions. So, whenever a new version is released, you test your app as needed, verify it working (and fix it if needed), and then update the manifest accordingly. Until then, Windows will down-grade itself to behave like the highest OS version that you have reported in your manifest.
You should not be relying on GetVersionEx() to control your app's functionality at runtime anyway. It is fine for reporting the OS version in logs and such (and there are other ways to get the true OS version regardless of manifestation), but don't make decisions based on OS version. For instance, if want to use a given feature that is only available in recent OS versions, don't check the OS version, check for the existence of the feature itself and use it if it is available.
Related
I'm working on an app that, due to restrictions that are beyond my control, is being built as an x86_64 app using an outdated macOS SDK (in this case the macOS 10.15 SDK).
It runs fine on an Apple Silicon mac using Rosetta 2, but the app needs to get the current version of macOS, and the available APIs lie to it under these conditions, consistently reporting the version is 10.16 when really it should be macOS 11.x or 12.x.
In other circumstances where the system API lies, I've been able to get the real info using sysctl, but in this case calling sysctlbyname("kern.osproductversion", ...) still lies to my app and reports 10.16.
How can I get the true version of macOS under these circumstances?
The only solution I've found so far is to launch the sysctl command line utility as a separate process and use it to query the system version. Here's a C++ implementation using Qt:
QProcess *p = new QProcess;
p->setProgram("/usr/sbin/sysctl");
p->setArguments({"-b", "kern.osproductversion"});
p->start();
if (!p->waitForFinished(2000)) {
// handle unlikely error here
}
QByteArray systemVersion = p->readAllStandardOutput();
On the bright side, this only ever needs to be executed once as the system version presumably won't change over the course of a process's life. Nonetheless I'll leave this question open in case someone has a better solution.
My application needs to determine whether it is running on Windows PE.
Neither the deprecated GetVersionEx function nor the preferred alternative Version Helper APIs offer any indication whether I am operating on WinPE, only indicating the version of the OS.
This reference lists the compatible APIs for WinPE, so I need to be able limit my app to those APIs.
How can I programmatically determine from my App whether I am on WinPE, and which PE version is running?
If you simply need to determine whether you are running WinPE or not, you can check for the presence of the key MiniNT in HKLM\System\CurrentControlSet\Control or HKLM\System\ControlSet001\Control. If it is present, you are on WinPE 2.x or higher.
Cited in MSDN docs here, you can see which version of Windows PE youare running at the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinPE. That reference also gives a table of features and functionality each version will provide you.
For very old versions of Windows/WinPE before 2.0, check the version of %SYSTEMROOT%\SYSTEM32\FACTORY.EXE.
I have scenarios where i want to specifically know the OS major/minor version and build number etc.
From windows 8.1 onwards GetVersion and GetVersionEx have been deprecated, stating:
[GetVersion/GetVersionEx may be altered or unavailable for releases after Windows 8.1. Instead, use the Version Helper functions]
None of the version helper APIs help me get the OS version number rather help me verify or get to know if my version is same or above some mentioned version. What can be done?
The API GetVersionEx() continues to work in Windows 8.1+, but Microsoft has altered its functionality. From MSDN (emphasis mine):
With the release of Windows 8.1, the behavior of the GetVersionEx API
has changed in the value it will return for the operating system
version. The value returned by the GetVersionEx function now depends
on how the application is manifested.
Applications not manifested for Windows 8.1 will return the Windows 8
OS version value (6.2). Once an application is manifested for a given
operating system version, GetVersionEx will always return the version
that the application is manifested for in future releases. To manifest
your applications for Windows 8.1 please refer to Targeting your
application for Windows 8.1.
What you need to do is add the proper GUID(s) to your application (.exe/.dll) binaries (via manifest XML information). In other words, if you specifically state your application supports 8.1, GetVersionEx() will return proper information when running on Windows 8.1. If you do not, GetVersionEx() will lie to you.
See Targeting your application For Windows 8.1 for a list of GUIDs.
Also covered here and here.
GUID List for the Lazy
Vista / Server 2008: {e2011457-1546-43c5-a5fe-008deee3d3f0}
Windows 7 / Server 2008 R2: {35138b9a-5d96-4fbd-8e2d-a2440225f93a}
Windows 8 / Server 2012: {4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}
Windows 8.1 / Server 2012 R2 : {1f676c76-80e1-4239-95bb-83d0f6d0da78}
Windows 10 / Server 2016: {8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}
As for Windows Server 2019, I'm not sure that a new GUID has been released. Please comment if you know more!
There is a new function named GetProductInfo that returns version infos.
If you want to test for a specific version you should use even VerifyVersionInfo
It is easy to create a structure to check whether a specific OS version is running. VerifyVersionInfo takes to version structures and you can easily check for VER_GREATER_EQUAL and VER_LESS_EQUAL
Also note that GetVersionEx doesn't lie on a Windows 8.1 system if you define the correct supported OS entry in the compatibility section for your manifest. But it may lie in a future OS version!
See Targeting your application For Windows 8.1 for a list of GUIDs. Also covered here.
GUID list for the application manifest
Vista: {e2011457-1546-43c5-a5fe-008deee3d3f0}
Windows 7: {35138b9a-5d96-4fbd-8e2d-a2440225f93a}
Windows 8: {4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}
Windows 8.1: {1f676c76-80e1-4239-95bb-83d0f6d0da78}
Windows 10: {8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}
Check this article on codeproject.com, It's working perfectly for Windows 8 :
1) Download .DLL and add it to your project .
2) Use this code to get Operation System Information :
StringBuilder sb = new StringBuilder(String.Empty);
sb.AppendLine("Operation System Information");
sb.AppendLine("----------------------------");
sb.AppendLine(String.Format("Name = {0}", OSVersionInfo.Name));
sb.AppendLine(String.Format("Edition = {0}", OSVersionInfo.Edition));
if (OSVersionInfo.ServicePack!=string.Empty)
sb.AppendLine(String.Format("Service Pack = {0}", OSVersionInfo.ServicePack));
else
sb.AppendLine("Service Pack = None");
sb.AppendLine(String.Format("Version = {0}", OSVersionInfo.VersionString));
sb.AppendLine(String.Format("ProcessorBits = {0}", OSVersionInfo.ProcessorBits));
sb.AppendLine(String.Format("OSBits = {0}", OSVersionInfo.OSBits));
sb.AppendLine(String.Format("ProgramBits = {0}", OSVersionInfo.ProgramBits));
textBox1.Text = sb.ToString();
Starting with Windows 8.1, GetVersionEx no longer returns the "true" version number, but might return a lower value.
There a no service packs for Windows 8 or Windows 8.1 yet, but when they are available, will GetVersionEx lie about them (wServicePackMajor and wServicePackMinor in OSVERSIONINFOEX) as well?
Microsoft forever does battle with well-intended code that a programmer writes to check the Windows version. Which was typically written to deal with older Windows versions. But forgets to do something reasonable with a newer Windows version.
So they spend massive amounts of effort on targeted compatibility shims that intentionally lie about the Windows version when a specific program asks for it. A never-ending battle whenever they release a new Windows version. Certainly a losing battle, the number of programs they need to test is staggering.
So at Windows 8.1 they said "no more", deprecated GetVersionEx() and intentionally lie out of the box, returning version 8.0. You need to add an entry to the manifest to turn off the lie. Which probably will turn off a lie about the service pack as well. Or might require an updated GUID, fairly unlikely. We of course can't be sure until that happens.
I am programming software in Java 7. The users of the software are not all up to date (especially the Mac users). Therefore I need an installer (Windows/OSX) that can be easily integrated with the software installation. There is a normal installer for Windows 7 so I am especially focused on finding one for the Mac. Bonus points if it can check for XCode and other requirements too).
I am thinking another option would be to just use some of the libraries from Java 7 (for example the file-system library). However, I think this might not be possible due to the version number in the compiled classes? I couldn't use a Java 6 compiler to compile these libraries either (because they are Java 7 code).
I don't think I am the only one with this problem. There must be a solution somewhere, but I haven't found it.
Any help would be appreciated.
For the best user experience I would recommend using PackageMaker to create a .pkg file which you can then give to your Mac users. That allows them to do a single click-to-install of your app.
Within the package you would bundle your app archive (JAR file), any necessary resources and two scripts, one to check for the existence of Java 7 on the target system, and the other to install it if not found. I would recommend bundling the latest version of OpenJDK7 with your pkg, at least until an official Java 7 SDK is released for the Mac.
JAva 7 is not yet officially supported on Mac OS X, if you are looking for a JAva 7 installer for mac Os X take a look at openjdk-osx-build project on Google Code.
Update: You shouldn't need Java 7 for what your doing.
A better solution is to use Java 6 + Third party JNI libraries (i.e: JNotify,JavaXT...)
Directory listener in Java using JNotify
as for Last Accessed Date you might need to write tiny bit of Objective-C and pass it back via JNI
JNI Development on Mac OS X
Mac OS X already comes with Java runtime on Snow Leopard (JRE6)
On Lion it will automatically download JRE6 if application needs it's
You can of course download preview release of JDK7 from Oracle, but remember this is preview software there are some parts still not working yet (for example: Java Web Start)
Oracle JDK7u4 Mac OS X Port Developer Preview Release
Edit: Oracle JDK 1.7 Preview Release only supports Mac OS X Lion