Internet Explorer 10 User Agent Strings On Windows 8 64bit

Internet Explorer 10 is the web browser Microsoft is delivering with Windows 8.

According to its different usages and modes, its user agent string is as follows:

Application Environment 32/64 bit User Agent String
Internet Explorer Metro - Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)
Javascript Application Metro - Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0;)
C#/VB Application Metro 32bit Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
C#/VB Application Metro 64bit Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)
Internet Explorer Desktop 32bit
Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Internet Explorer Desktop 64bit(1) Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)
WPF Application Desktop 32bit Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; Tablet PC 2.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Zune 4.7; InfoPath.3)
WPF Application Desktop 64bit Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/6.0; .NET4.0E; .NET4.0C; Tablet PC 2.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Zune 4.7; InfoPath.3)
(1) Needs to be enabled for each security zone.

Analyzing the above table I conclude that:

  1. Metro Internet Explorer is always a 64bit application on 64bit Windows 8.
  2. Javascript Metro Style Applications don’t announce if they are 32bit or 64bit.
    1. They look like they are running on a 32bit Windows 8.
  3. Desktop Internet Explorer retains the same behavior introduced with Internet Explorer 8.
  4. Metro Style C#/VB Applications hosting the web browser (WebView control) exhibit the same behavior as Internet Explorer.
  5. Desktop WPF Applications hosting the web browser (WebBrowser control) retain the same behavior introduced with Internet Explorer 8.

Detecting User Regional Settings In The Web Browser

Recently, a friend of mine asked me something like: “How do I get the user’s regional settings for a request to a web server?”

As far as I know, web browser only send an Accept-Language HTTP header and nothing more. You can take this and use the default regional settings for that language but, if your user is anything like me, you’ll be wrong.

So, what’s the problem of getting it wrong?

If you are just generating HTML and keep it consistent, nothing’s wrong. But what if your user wants to copy some numeric and/or date values to, say, Excel? Or if you want to export some data as a CSV file?

A solution

Going through the JScript Language Reference, I found that both Number and Date have locale related toString methods and I started playing with them.

Numeric format settings

To the numeric format settings, first we need a number that will behave in a predictable manner in any culture (“any culture” means “any culture I know”) and for all possible settings and convert it to a string using the toLocaleString method:

var number = 111111111.111111111;
var numberString = number.toLocaleString();

(With my regional settings, numberString becomes 111 111 111.11)

To get the decimal separator, all it takes is getting the first non 1 from the end:

var decimalSeparator;
var decimalDigits;
for (var i = numberString.length - 1; i >= 0; i--) {
    var char = numberString.charAt(i);
    if (char != "1") {
        decimalSeparator = char;
        decimalDigits = numberString.length - i - 1;

And if you count how many 1s were skipped, we get the number of decimal digits.

In a similar way, the first non 1 will be the digit grouping separator:

var groupSeparator;
for (var i = 0; i < numberString.length; i++) {
    var char = numberString.charAt(i);
    if (char != "1") {
        groupSeparator = char;

Now that we have the digit grouping separator, we can get the digit groups (these groups might not all have the same size):

var digitGrouping = numberString.substring(0, numberString.length - decimalDigits - 1).split(groupSeparator);
for (g in digitGrouping) {
    digitGrouping[g] = digitGrouping[g].length;
Date and time settings

Date and time values are more difficult to parse and you might not need all information. So, I’ll just get the value and let the parsing to you:

var dateTime = new Date(9999, 11, 31, 23, 30, 45);
dateTimeString = dateTime.toLocaleString();
List settings

The last setting is the list separator (very useful for those CSV files):

var list = ["a", "b"];
listSeparator = list.toLocaleString().substring(1, 2);

Test page

Here is a test page the get all these settings:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <title>Test Page</title>
    <style type="text/css">
        label  { width: 8em; text-align: right; padding-right: 0.5em; white-space: nowrap; }
        span { border: 1px solid; white-space: nowrap; }
    <script type="text/javascript">
        function init() {
            document.all.userLanguage.innerText = window.navigator.userLanguage;
            document.all.systemLanguage.innerText = window.navigator.systemLanguage;

            // Decimal separator and decimal digits
            var number = 111111111.111111111;
            var numberString = (111111111.111111111).toLocaleString();

            var decimalSeparator;
            var decimalDigits;
            for (var i = numberString.length - 1; i >= 0; i--) {
                var char = numberString.charAt(i);
                if (char != "1") {
                    decimalSeparator = char;
                    decimalDigits = numberString.length - i - 1;
            document.all.decimalSeparator.innerText = decimalSeparator;
            document.all.decimalDigits.innerText = decimalDigits;

            // Digit grouping separator and digit goups
            var groupSeparator;
            for (var i = 0; i < numberString.length; i++) {
                var char = numberString.charAt(i);
                if (char != "1") {
                    groupSeparator = char;
            document.all.groupSeparator.innerText = groupSeparator;

            var digitGrouping = numberString.substring(0, numberString.length - decimalDigits - 1).split(groupSeparator);
            for (g in digitGrouping) {
                digitGrouping[g] = digitGrouping[g].length;
            document.all.digitGrouping.innerText = digitGrouping.toString();

            // Date format
            var dateTime = new Date(9999, 11, 31, 23, 30, 45);
            var dateTimeString = dateTime.toLocaleString();
            document.all.dateTimeFormat.innerText = dateTimeString;

            // List separator
            var list = ["a", "b"];
            var listSeparator = list.toLocaleString().substring(1, 2);
            document.all.listSeparator.innerText = listSeparator;
<body onload="init()">
    <p><label for="userLanguage">User language:</label><span id="userLanguage"></span></p>
    <p><label for="systemLanguage">System language:</label><span id="systemLanguage"></span></p>
    <p><label for="decimalSeparator">Decimal separator:</label><span id="decimalSeparator"></span></p>
    <p><label for="decimalDigits">Decimal digits:</label><span id="decimalDigits"></span></p>
    <p><label for="groupSeparator">Digit separator:</label><span id="groupSeparator"></span></p>
    <p><label for="digitGrouping">Digit grouping:</label><span id="digitGrouping"></span></p>
    <p><label for="dateTimeFormat">Date/Time format:</label><span id="dateTimeFormat"></span></p>
    <p><label for="listSeparator">List separator:</label><span id="listSeparator"></span></p>

Defining Document Compatibility In Internet Explorer 8

The procedures to define document compatibility in Internet Explorer 8 are well documented here, but I’ve seem many developers and system administrators that are not aware of this.

Although you can (and should) define the document compatibility your web pages were designed to, if you don’t, Internet Explorer 8 and the Web Browser Control will default to these compatibility modes:




Internet Explorer 8 IE7 mode IE8 mode
Application hosting the Web Browser Control IE7 mode IE7 mode

If you notice the table above, by default, only Internet Explore 8 will present itself to the as Internet Explorer 8 and only to Internet sites.

The way Internet Explorer (and any other browser) presents itself the web servers is using its user agent string:


User Agent String

IE7 Mozilla/4.0 (compatible; MSIE 7.0; …; Trident/4.0; …)
IE8 Mozilla/4.0 (compatible; MSIE 8.0; …; Trident/4.0; …)

(If you are curious about the history of the user-agent string, read the History of the user-agent string)

Microsoft did this to keep compatibility with legacy applications used by enterprises (large and small) but this brings a few issues to development and testing.

If you are building a public web site for Internet Explorer 8, you might see the right thing on your development machine, but the quality assurance team will see the site as if it were an Internet Explorer 7 if the version they are testing is on the intranet. If the the web site you are developing is going to be accessed from an application hosting the Web Browser Control and you don’t test on that application, you are not going to see the same thing.

To know how is your browser presenting itself to the web server in the internet, there are several web sites that will show information about the user-agent string (like http://www.useragents.org/) and it helps to have the same thing in your intranet. If you want to build such a web application using ASP.NET, you can use the UserAgent property of the HttpRequest class (or the Browser property for more detailed information).

This type of information is also available in Internet Explorer in the navigator object.

Giorgio Sardo has a few functions to detect Internet Explorer 8 but you might also want to develop a diagnostics page (or part) to show the web browser features, something like this:

<fieldset id="webBrowserInfo">
    <legend>Web Browser</legend>
    <table border="1">
            <td class="label" style="width: 100px"><label for="webBrowser$userAgent">userAgent</label> </td>
            <td class="value" colspan="3"><span id="webBrowser$userAgent"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$appVersion">appVersion</label></td>
            <td class="value"><span id="webBrowser$appVersion"></span></td>
            <td class="label"><label for="webBrowser$appMinorVersion">appMinorVersion</label></td>
            <td class="value"><span id="webBrowser$appMinorVersion"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$appCodeName" style="width: 600px">appCodeName</label></td>
            <td class="value" colspan="3"><span id="webBrowser$appCodeName"></span></td>
            <td class="label"><label for="webBrowser$appName">appName</label></td>
            <td class="value" colspan="3"><span id="webBrowser$appName"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$userLanguage">userLanguage</label></td>
            <td class="value"><span id="webBrowser$userLanguage"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$cpuClass">cpuClass</label></td>
            <td class="value"><span id="webBrowser$cpuClass"></span></td>
            <td class="label"><label for="webBrowser$systemLanguage">systemLanguage</label></td>
            <td class="value"><span id="webBrowser$systemLanguage"></span></td>
            <td class="label"><label for="webBrowser$platform">platform</label></td>
            <td class="value"><span id="webBrowser$platform"></span></td>
            <td class="label"><label for="webBrowser$browserLanguage">browserLanguage</label></td>
            <td class="value"><span id="webBrowser$browserLanguage"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$cookieEnabled">cookieEnabled</label></td>
            <td class="value" colspan="5"><span id="webBrowser$cookieEnabled"></span></td>

<script type="text/javascript">
    document.getElementById("webBrowser$userAgent").innerHTML = window.navigator.userAgent;
    document.getElementById("webBrowser$appCodeName").innerHTML = window.navigator.appCodeName;
    document.getElementById("webBrowser$appMinorVersion").innerHTML = window.navigator.appMinorVersion;
    document.getElementById("webBrowser$appName").innerHTML = window.navigator.appName;
    document.getElementById("webBrowser$appVersion").innerHTML = window.navigator.appVersion;
    document.getElementById("webBrowser$browserLanguage").innerHTML = window.navigator.browserLanguage;
    document.getElementById("webBrowser$cookieEnabled").innerHTML = window.navigator.cookieEnabled;
    document.getElementById("webBrowser$cpuClass").innerHTML = window.navigator.cpuClass;
    document.getElementById("webBrowser$platform").innerHTML = window.navigator.platform;
    document.getElementById("webBrowser$systemLanguage").innerHTML = window.navigator.systemLanguage;
    document.getElementById("webBrowser$userLanguage").innerHTML = window.navigator.userLanguage;

Extended WebBrowser Control – Version Uploaded

After a long time, I finally managed to upload a version of the Extended WebBrowser Control to CodePlex.

It's still a work in progress, but it's usable. Feel free to download, comment and file issues. A nice tabbed browser demo is included.

Microsoft, Eurocrats And Internet Explorer

I’m all against monopolies, so I’m glad the Eurocrats are putting my tax payer Euros to good use.

But it also got me thinking.

If I buy something like an operating system, I expect the vendor to be responsible for what I’m buying. Does anyone think Microsoft will ever accept any responsibility for software that it hasn’t built and is forced to bundle into its products. They probably make some disclaimer like “We didn’t build this. We were forced to put this here and we totally discourage its use.”. That will boost other browsers.

Probably the Eurocrats are planning to take that responsibility themselves. I think there’s a greater possibility for Microsoft to take responsibility for something they didn’t built and were forced to bundle into their products.

On the other hand, a personal computer is becoming something like an household appliance. Do you expect to download a timer for your microwave oven before being able to use it? I don’t.

Internet Explorer is built to be parte of Windows and to be freely used by any application running on Windows. Any other we browser could be built the same way, why aren’t they?

Why isn’t anyone thinking of forcing Microsoft to allow for third party components to replace parts of Internet Explorer? Probably because no one cares about build applications that are good Windows “citizens”.

Internet Explorer 8 RC 1 has now been released!

Internet Explorer 8 RC 1 has now been released! You can get it here.

Before installing, please read the Release Notes and more information about features and developer docs can be found in the IE8 Readiness Toolkit.

Internet Explorer 8 RC 1 is now platform and feature complete and this is our opportunity to try out the new browser before its final release. If you find issues with IE8, please file a bug. More information and instructions can be found at the support page for Internet Explorer 8 RC 1.

To ensure your browser is up to date, all RC1 users will be automatically updated with the final version of Internet Explorer 8 via Windows Update so you'll always have the latest version of the browser.

Setting A Web Proxy Through Configuration In .NET Applications

Specially in enterprise environments, proxy servers are used to access the Internet.

In a Windows / Internet Explorer environments there is a proxy server configuration in Internet Properties > Connections > LAN settings > Proxy server.

Although these configurations are tightly connected to Internet Explorer, any well behaved Windows application should, at least, allow the user to choose to use them.

In applications targeting the .NET framework, these the proxy server can be set on a per call basis. Several networking classes have a Proxy property that receives a value implementing the IWebProxy interface.

In order for the Windows/ Internet Explorer configuration to be used, the application must be configured to use the default proxy settings.

This configuration is done in the machine or application file in the proxy element of the defaultProxy configuration section in the system.net section group:

    <defaultProxy enabled="true">
      <proxy usesystemdefault="True"/>

You can use this configuration also to set a specific proxy to be used by your application. In the following example, a proxy setting for using the Fiddler Tool is used:

    <defaultProxy enabled="true">
      <proxy proxyaddress="http://ipv4.fiddler"/>
      <proxy proxyaddress=""/>

Unfortunately, this is a MachineToApplication setting and, for that reason, is not allowed in the user settings configuration file, when in a shared installation. In these type of installations, the default Windows / Internet Explorer settings should be used as a default. If a user needs or wants to specify proxy server settings, application specific proxy server settings must be used but, assigning the user defined proxy server configuration to the GlobalProxySelection.Select property will allow its use for the entire application.

Updated: Corrected proxy address when using Fiddler following Eric Lawrence’s comment:

> <proxy proxyaddress="http://ipv4.fiddler/" />

That line should not work. Fiddler doesn't register anything in DNS, so for "ipv4.fiddler" to have any meaning, Fiddler must already be being used as the proxy.

The proper setting for Fiddler use should be:

<proxy proxyaddress="" />

The Problem Of Long Web Browser User-Agent Strings

Every web browser sends, on every request, a user-agent request HTTP header to the server.

If you are curious about how Internet Explorer’s user-agent string is form, read this article.

This information is used by server software to identify the web browser the user is using and its capabilities and determine if it’s enough for use in this web site or to perform differentiate rendering.

In the past there have been several reports of user-agent string buffer overrun attacks and some web servers and firewalls have chosen to block access to requests that have a user-agent string over some length.

The problem that arrives now is that, due to other software installed in the user’s system, the user-agent string has been growing past the limit allowed by some web servers and firewalls.

As an example, my web browser’s user-agent string, at this moment, is:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; Zune 3.0; OfficeLiveConnector.1.3; OfficeLivePatch.1.3; MS-RTC LM 8; SPC 3.1 P1 Ta)

With a user-agent string like this (275 characters long) I’ve been locked out of sever sites.

More On ASP.NET Validators And Validation Summary Rendering of Properties

On previous posts [^][^] I mentioned the size of ASP.NET validators and validation summary rendering and the fact that expando attributes are being used to add properties. Mohamed also mentions this issue.

Besides the fact that custom attributes aren't XHTML conformant, Firefox differs from Internet Explorer in the way it handles these attributes.

On Internet Explorer, these attributes are converted in string properties of the HTML element. On Firefox, on the other hand, these attributes are only accessible through the attributes collection.

I wonder why I don’t like client-side JavaScript development.

Testing With Multiple Versions Of Internet Explorer

On a previous post I mentioned IETester.

Jorge Moura mentioned TredoSoft’s MultipleIEs and a list of web browsers.