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.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
user1725145
  • 3,993
  • 2
  • 37
  • 58

3 Answers3

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) { ... }
Vijay Nirmal
  • 5,239
  • 4
  • 26
  • 59
Justin XL
  • 38,763
  • 7
  • 88
  • 133
  • Thanks! I'm off to try this. What about using IsMethodPresent for individual methods, is that a non-starter do you think? – user1725145 Aug 03 '17 at 10:03
  • 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. – Justin XL Aug 03 '17 at 10:13
  • I have to support different Windows versions for enterprises, and yes, we do only check once! – user1725145 Aug 03 '17 at 10:15
  • 2
    @JustinXL `FallCreators = 1709` – Vijay Nirmal Aug 03 '17 at 11:11
  • I have extended it to cater for `AreEffectsFast` and `AreEffectsSupported` in Creators Update. If you ever use Composition, you may find them helpful. – Justin XL Aug 03 '17 at 11:24
  • Thank you, those are interesting. Code runs, still got to do the WACK test. – user1725145 Aug 03 '17 at 12:12
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

Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
Blue
  • 312
  • 2
  • 12
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

Vijay Nirmal
  • 5,239
  • 4
  • 26
  • 59
  • 1
    If you check its source, it's actually using @Blue's answer below though. – Justin XL Aug 03 '17 at 11:25
  • @JustinXL I have tested this code. It successfully passed the WACK test. – Vijay Nirmal Aug 03 '17 at 12:34
  • 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. – user1725145 Aug 03 '17 at 12:51
  • 1
    @JustinXL According to [nmetulev](https://github.com/nmetulev), This is probably caused by an older version of the WACK. Source: [WACK test FAILED due to SystemInformation.OperatingSystemVersion](https://github.com/Microsoft/UWPCommunityToolkit/issues/1367#issuecomment-320524853) – Vijay Nirmal Aug 06 '17 at 19:27
  • Thanks @VijayNirmal – user1725145 Aug 07 '17 at 08:03
  • @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). – user1725145 Aug 08 '17 at 07:09