On Wed, Apr 27, 2022 at 03:04:23PM +0000, Wilm Hoyer wrote:
>>
>> I used the following hack to get the "real" Major and Minor Version of 
>> Windows - it's in C# (.Net) and needs to be adjusted (you can compile 
>> as x64 and use a long-long as return value ) to return the Service 
>> Number too and translated it into C.
>> I share it anyways, as it might help - please be kind, as it really is 
>> a little hack.
>>
>> Situation:
>> Main Application can't or is not willing to add a manifest file into 
>> its resources.
>>
>> Solution:
>> Start a small executable (which has a manifest file compiled into its 
>> resources), let it read the OS Version and code the Version into its 
>> return Code.

> Thanks for sharing.

You are welcome.

> Having to compile another tool just for that seems like a very high price to 
> pay, especially since we don't have any C# code in the tree.  I'm not even 
> sure that compiling this wouldn't need additional  requirements and/or if it 
> would work on our oldest supported Windows versions.

With "translate it into C" I meant "tread it as pseudo code, for a solution in 
plain C" (e.g. substitude Environment.OSVersion with IsWindowsVersionOrGreater 
or GetVersion )

On Wed, Apr 27, 2022 at 05:13:12PM +0900, Michael Paquier wrote:
> On Tue, Apr 26, 2022 at 12:54:35PM +0800, Julien Rouhaud wrote:
> > so I'm still on the opinion that we should unconditionally use the 
> > FILE_MAP_LARGE_PAGES flag if it's defined and call it a day.
> 
> Are we sure that this is not going to cause failures in environments 
> where the flag is not supported?

I'm not that familiar with the Microsoft OS or C (that's why I haven't migrated 
the c# code to C in the first place) to have a clear answer to that question.

If there is any risk and you want to avoid it, I can share a search result when 
I faced the same issue for our application. I declined this solution in favor 
of the previously shared one.
It's from NUnit (and needs migration to C as well - but since it just involves 
the Registry this should be pretty forward).
Just in case the Framework is not known: NUnit is the most popular .Net port of 
the Unit Testing Framework JUnit. There exits a C port too (CUnit) Maybe in 
there you can find an OS Version check too.

// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see 
LICENSE.txt
[...]
namespace NUnit.Framework.Internal
{
    [SecuritySafeCritical]
    public class OSPlatform
    {
[...]
        /// <summary>
        /// Gets the actual OS Version, not the incorrect value that might be
        /// returned for Win 8.1 and Win 10
        /// </summary>
        /// <remarks>
        /// If an application is not manifested as Windows 8.1 or Windows 10,
        /// the version returned from Environment.OSVersion will not be 6.3 and 
10.0
        /// respectively, but will be 6.2 and 6.3. The correct value can be 
found in
        /// the registry.
        /// </remarks>
        /// <param name="version">The original version</param>
        /// <returns>The correct OS version</returns>
        private static Version GetWindows81PlusVersion(Version version)
        {
            try
            {
                using (var key = 
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows 
NT\CurrentVersion"))
                {
                    if (key != null)
                    {
                        var buildStr = key.GetValue("CurrentBuildNumber") as 
string;
                        int.TryParse(buildStr, out var build);

                        // These two keys are in Windows 10 only and are DWORDS
                        var major = key.GetValue("CurrentMajorVersionNumber") 
as int?;
                        var minor = key.GetValue("CurrentMinorVersionNumber") 
as int?;
                        if (major.HasValue && minor.HasValue)
                        {
                            return new Version(major.Value, minor.Value, build);
                        }

                        // If we get here, we are not Windows 10, so we are 
Windows 8
                        // or 8.1. 8.1 might report itself as 6.2, but will 
have 6.3
                        // in the registry. We can't do this earlier because 
for backwards
                        // compatibility, Windows 10 also has 6.3 for this key.
                        var currentVersion = key.GetValue("CurrentVersion") as 
string;
                        if(currentVersion == "6.3")
                        {
                            return new Version(6, 3, build);
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            return version;
        }
[...]
   }
}

Finally, my reasoning to use the executable solution in favor of the NUnit one: 
I found no guarantee from Microsoft regarding the keys and values in the 
registry - hence a change with an update or in a newer Windows is not likely, 
but still possible. That's no problem for a heavily used and supported 
framework like NUnit - they are likely to adopt within days of a new Windows 
release. I on the other hand wanted a solution with small to no support. That's 
why I decided to implement a solution that's as in line as possible with the 
official Microsoft advice for targeting newer OS Versions.

Best regards
Wilm.


Reply via email to