michielpost.nl

Secret little hack to get the OS version in Windows 8

07-08-2012

You can download the code as part of the Q42.WinRT open source toolkit for Windows 8.

WinRT does not have an API method to get the OS version. Metro apps run in a sandbox and shouldn't care about the OS version. Microsoft's guidance is to make your apps independent of the OS version and rather look at the capabilities needed for your application (like specific sensors).

But maybe you still want to know the OS version. For example for logging exceptions, or to keep statistics when an API is used by different platforms. So I figured out a way to do this.

I noticed that the WebView control sends a full user agent string with each request, including the OS version "Windows NT 6.2":

User agent string:
Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0)

It's possible to get the User Agent with JavaScript using this method:
function GetUserAgent()
{
      return navigator.userAgent;
}

Next step is to get this string back into my managed code. It's possible to invoke JavaScript methods on the WebView control and get the result:
string result = webView.InvokeScript("GetUserAgent", null);

When loading our custom HTML, we have to wait for the LoadCompleted event before we can invoke the script on the WebView. That's why we wrap this code in a task. Putting it all together, we now have a method to get the UserAgent string:

private static Task<string> GetUserAgent()
{

  var tcs = new TaskCompletionSource<string>();
  WebView webView = new WebView();

  string htmlFragment = @"<html>

                    <head>
                        <script type='text/javascript'>
                            function GetUserAgent()
                            {
                                return navigator.userAgent;
                            }
                        </script>
                    </head>
                </html>";

  webView.LoadCompleted += (sender, e) =>
  {

    try
    {
      //Invoke the javascript when the html load is complete
      string result = webView.InvokeScript("GetUserAgent", null);

      //Set the task result
      tcs.TrySetResult(result);

    }
    catch(Exception ex)
    {
      tcs.TrySetException(ex);
    }

  };

  //Load Html
  webView.NavigateToString(htmlFragment);

  return tcs.Task;
}

Now we only have to parse this string to get the OS version:

public static async Task<string> GetOsVersionAsync()
{

  string userAgent = await GetUserAgent();

  string result = string.Empty;

  //Parse user agent
  int startIndex = userAgent.ToLower().IndexOf("windows");
  if (startIndex > 0)
  {
    int endIndex = userAgent.IndexOf(";", startIndex);

    if (endIndex > startIndex)
      result = userAgent.Substring(startIndex, endIndex - startIndex);

  }

  return result;

}

This method will return: Windows NT 6.2

Note: there's no guarantee this will also work in future versions of the OS.

Comments


No comments yet.

New Comment

Name
E-mail (not published)
Comment
Enter the code shown: