How to check the Windows 10 OS version in an UWP app so as to eliminate WACK test fail?
Asked Answered
S

3

5

I am working on an UWP app that uses some features that aren't available in older versions of Windows 10. Therefore, I need to check if Creators Update is installed.

There is version-checking code in the app using AnalyticsInfo.VersionInfo. However, the latest round of WACK tests gave the following Fail:

FAILED Platform version launch • Error Found: The high OS version validation detected the following errors:

o Failed to stop the app AppName.group.mbb.

o The app Company.AppName_2.3.56045.0_x64__cx08jceyq9bcp failed platform version launch test.

• Impact if not fixed: The app should not use version information to provide functionality that is specific to the OS.

• How to fix: Please use recommended methods to check for available functionality in the OS. See the link below for more information. Operating System Version

I am aware of this question, but would rather fix the Fail if possible. I found advice on MSDN about how to make a UWP app "version adaptive" here.

I now have this code:

using Windows.Foundation.Metadata;

if (ApiInformation.IsMethodPresent("Windows.Networking.Connectivity.ConnectionProfile", "GetNetworkUsageAsync"))
    {
        //do stuff
    }

My Windows version is 1703 15063.483, and GetNetworkUsageAsync is used successfully elsewhere in the code. But the call to IsMethodPresent always returns false.

What is wrong with my code?
And is there a better function to check, to know if Creators Update is installed?

UPDATE: I followed Microsoft guidelines for the above Fail, and changed the version checking from AnalyticsInfo.VersionInfo to Windows.Foundation.Metadata.ApiInformation. The app still fails the WACK test with the same error.

2ND UPDATE:
After updating Windows10 to Creators Update, Build 16251.0, this error disappeared on my computer.

Subchloride answered 3/8, 2017 at 9:30 Comment(2)
I have tested your code It returns true for me.Muriah
Thanks Vijay. I don't know why it always gave false for me.Subchloride
U
10

Maybe a little bit helper class like this? Note calling this could be costly so it's recommended to do this once and cache the data.

(Update: If you use Windows Composition API, you will find AreEffectsFast and AreEffectsSupported helpful as you can use them to toggle effects on and off based on user's device and OS conditions. I have extended the class below to expose them as two new properties.)

public class BuildInfo
{
    private static BuildInfo _buildInfo;

    private BuildInfo()
    {
        if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 5))
        {
            Build = Build.FallCreators;
        }
        else if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 4))
        {
            Build = Build.Creators;
        }
        else if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3))
        {
            Build = Build.Anniversary;
        }
        else if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 2))
        {
            Build = Build.Threshold2;
        }
        else if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 1))
        {
            Build = Build.Threshold1;
        }
        else
        {
            Build = Build.Unknown;
        }

        if (!BeforeCreatorsUpdate)
        {
            var capabilities = CompositionCapabilities.GetForCurrentView();
            capabilities.Changed += (s, e) => UpdateCapabilities(capabilities);
            UpdateCapabilities(capabilities);
        }

        void UpdateCapabilities(CompositionCapabilities capabilities)
        {
            AreEffectsSupported = capabilities.AreEffectsSupported();
            AreEffectsFast = capabilities.AreEffectsFast();
        }
    }

    public static Build Build { get; private set; }
    public static bool AreEffectsFast { get; private set; }
    public static bool AreEffectsSupported { get; private set; }
    public static bool BeforeCreatorsUpdate => Build < Build.Creators;

    public static BuildInfo RetrieveApiInfo() => _buildInfo ?? (_buildInfo = new BuildInfo());
}

public enum Build
{
    Unknown = 0,
    Threshold1 = 1507,   // 10240
    Threshold2 = 1511,   // 10586
    Anniversary = 1607,  // 14393 Redstone 1
    Creators = 1703,     // 15063 Redstone 2
    FallCreators = 1709  // 16299 Redstone 3
}

To initialize the class, call it right after OnWindowCreated in your App.xaml.cs.

protected override void OnWindowCreated(WindowCreatedEventArgs args)
{
    BuildInfo.RetrieveBuildInfo();

To use it, simply call

if (BuildInfo.Build == Build.Anniversary) { ... }

if (BuildInfo.BeforeCreatorsUpdate) { ... }

if (BuildInfo.AreEffectsFast) { ... }
Unreligious answered 3/8, 2017 at 10:1 Comment(6)
Thanks! I'm off to try this. What about using IsMethodPresent for individual methods, is that a non-starter do you think?Subchloride
I normally just F12 on the method and check its api contract number to get which build it runs on and haven't particularly used individual checks like this. But feel free to add it inside the same helper class. The rule is just you only want to do the check once.Unreligious
I have to support different Windows versions for enterprises, and yes, we do only check once!Subchloride
@JustinXL FallCreators = 1709Muriah
I have extended it to cater for AreEffectsFast and AreEffectsSupported in Creators Update. If you ever use Composition, you may find them helpful.Unreligious
Thank you, those are interesting. Code runs, still got to do the WACK test.Subchloride
J
6

Try this

string deviceFamilyVersion= AnalyticsInfo.VersionInfo.DeviceFamilyVersion;
ulong version = ulong.Parse(deviceFamilyVersion);
ulong major = (version & 0xFFFF000000000000L) >> 48;
ulong minor = (version & 0x0000FFFF00000000L) >> 32;
ulong build = (version & 0x00000000FFFF0000L) >> 16;
ulong revision = (version & 0x000000000000FFFFL);
var osVersion = $"{major}.{minor}.{build}.{revision}";

Source:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/2d8a7dab-1bad-4405-b70d-768e4cb2af96/uwp-get-os-version-in-an-uwp-app?forum=wpdevelop

Jacklighter answered 3/8, 2017 at 9:43 Comment(3)
As I said in the question, this code seems to have caused the WACK test fail.Subchloride
Please provide attribution when borrowing other peoples code. I've updated your post to credit the original author.Mccullum
The WACK concern is old, now passes.Shira
M
2

Use SystemInformation Helper by UWPCommunityToolkit. Install Microsoft.Toolkit.Uwp Nuget package before using it.

public OSVersion OperatingSystemVersion => SystemInformation.OperatingSystemVersion;

Using this you can get other system info also like DeviceModel, DeviceManufacturer etc

For more info: SystemInformation

Muriah answered 3/8, 2017 at 11:10 Comment(6)
If you check its source, it's actually using @Blue's answer below though.Unreligious
@JustinXL I have tested this code. It successfully passed the WACK test.Muriah
We have had code using AnalyticsInfo.VersionInfo that has passed the WACK test as well though. But the error message for the Fail, specifically tells you to use Windows.Foundation.Metadata.ApiInformation. I don't understand why this fail comes and goes, or why another poster said that their app was accepted in the Windows Store despite failing the WACK test with this error. I'm just trying to make my code as safe as possible.Subchloride
@JustinXL According to nmetulev, This is probably caused by an older version of the WACK. Source: WACK test FAILED due to SystemInformation.OperatingSystemVersionMuriah
Thanks @VijayNirmalSubchloride
@VijayNirmal see my update to the question. Looks as though this is correct! The error seems to go away with Build 16251.0 (currently available from the Windows Insider program).Subchloride

© 2022 - 2024 — McMap. All rights reserved.