Configuring the emulation mode of an Internet Explorer WebBrowser control
Occasionally I need to embed HTML in my applications. If it is
just to display some simple layout with basic interactions, I
might use a component such as HtmlRenderer. In most cases
however, I need a more complex layout, JavaScript or I might
want to display real pages from the internet - in which case I'm
lumbered with the WebBrowser
control.
I'm aware other embeddable browsers exist, but the idea of shipping additional multi-MB dependencies doesn't make sense unless an application makes heavy use of HTML interfaces
The WebBrowser
control annoys me in myriad ways, but it does
get the job done. One of the things that occasionally frustrates
me is that by default it is essentially an embedded version of
Internet Explorer 7 - or enabling Compatibility Mode in a modern
IE session. Not so good as more and more sites use HTML5 and
other goodies.
Rather fortunately however, Microsoft provide the ability to configure the emulation mode your application will use. It's not as simple as setting some properties on a control as it involves setting some registry values and other caveats, but it is still a reasonable process.
About browser emulation versions
The table below (source) lists the currently supported
emulation versions at the time of writing. As you can see, it's
possible to emulate all "recent" versions of Internet Explorer
in one of two ways - either by forcing a standards mode, or
allowing !DOCTYPE
directives to control the mode. The
exception to this dual behaviour is version 7 which is as is.
According to the documentation the IE8 (8000) and IE9 (9000) modes will switch to IE10 (10000) mode if installed. The documentation doesn't mention if this is still the case regarding IE11 so I'm not sure on the behaviour in that regard.
Value | Description |
---|---|
11001 | Internet Explorer 11. Webpages are displayed in IE11 edge mode, regardless of the !DOCTYPE directive. |
11000 | IE11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 edge mode. Default value for IE11. |
10001 | Internet Explorer 10. Webpages are displayed in IE10 Standards mode, regardless of the !DOCTYPE directive. |
10000 | Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode. Default value for Internet Explorer 10. |
9999 | Windows Internet Explorer 9. Webpages are displayed in IE9 Standards mode, regardless of the !DOCTYPE directive. |
9000 | Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9. |
8888 | Webpages are displayed in IE8 Standards mode, regardless of the !DOCTYPE directive. |
8000 | Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8 |
7000 | Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control. |
Setting the browser emulation version
Setting the emulation version is very straightforward - add a value to the registry in the below key containing the name of your executable file and a value from the table above.
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
SOFTWARE
Microsoft
Internet Explorer
Main
FeatureControl
FEATURE_BROWSER_EMULATION
yourapp.exe = (DWORD) version
Note: If you do this from an application you're debugging using Visual Studio and the Visual Studio Hosting Process option is enabled you'll find the executable name may not be what you expect. When enabled, a stub process with a slightly modified name is used instead. For example, if your application is named
calc.exe,
you'll need to add the valuecalc.vshost.exe
in order to set the emulated version for the correct process.
Getting the Internet Explorer version
As it makes more sense to detect the version of IE installed on the user's computer and set the emulation version to match, first we need a way of detecting the IE version.
There are various ways of getting the installed IE version, but the sensible method is reading the value from the registry as everything else we are doing in this article involves the registry in some fashion.
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Internet Explorer
svcVersion or Version
Older versions of IE used the Version
value, while newer
versions use svcVersion
. In either case, this value contains
the version string.
We can use the following version to pull out the major digit.
private const string InternetExplorerRootKey = @"Software\Microsoft\Internet Explorer";
public static int GetInternetExplorerMajorVersion()
{
int result;
result = 0;
try
{
RegistryKey key;
key = Registry.LocalMachine.OpenSubKey(InternetExplorerRootKey);
if (key != null)
{
object value;
value = key.GetValue("svcVersion", null) ?? key.GetValue("Version", null);
if (value != null)
{
string version;
int separator;
version = value.ToString();
separator = version.IndexOf('.');
if (separator != -1)
{
int.TryParse(version.Substring(0, separator), out result);
}
}
}
}
catch (SecurityException)
{
// The user does not have the permissions required to read from the registry key.
}
catch (UnauthorizedAccessException)
{
// The user does not have the necessary registry rights.
}
return result;
}
Points to note
- I'm returning an
int
with the major version component rather aVersion
class. In this example, I don't need a full version to start with and it avoids crashes if the version string is invalid - For the same reason, I'm explicitly catching (and ignoring)
SecurityException
andUnauthorizedAccessException
exceptions which will be thrown if the user doesn't have permission to access those keys. Again, I don't really want the function crashing for those reasons.
You can always remove the try
block to have all exceptions
thrown instead of the access exceptions being ignored.
Getting the browser emulation version
The functions to get and set the emulation version are using
HKEY_CURRENT_USER
to make them per user rather than for the entire machine.
First we'll create an enumeration to handle the different versions described above so that we don't have to deal with magic numbers.
public enum BrowserEmulationVersion
{
Default = 0,
Version7 = 7000,
Version8 = 8000,
Version8Standards = 8888,
Version9 = 9000,
Version9Standards = 9999,
Version10 = 10000,
Version10Standards = 10001,
Version11 = 11000,
Version11Edge = 11001
}
Next, a function to detect the current emulation version in use by our application, and another to quickly tell if an emulation version has previously been set.
private const string BrowserEmulationKey = InternetExplorerRootKey + @"\Main\FeatureControl\FEATURE_BROWSER_EMULATION";
public static BrowserEmulationVersion GetBrowserEmulationVersion()
{
BrowserEmulationVersion result;
result = BrowserEmulationVersion.Default;
try
{
RegistryKey key;
key = Registry.CurrentUser.OpenSubKey(BrowserEmulationKey, true);
if (key != null)
{
string programName;
object value;
programName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
value = key.GetValue(programName, null);
if (value != null)
{
result = (BrowserEmulationVersion)Convert.ToInt32(value);
}
}
}
catch (SecurityException)
{
// The user does not have the permissions required to read from the registry key.
}
catch (UnauthorizedAccessException)
{
// The user does not have the necessary registry rights.
}
return result;
}
public static bool IsBrowserEmulationSet()
{
return GetBrowserEmulationVersion() != BrowserEmulationVersion.Default;
}
Setting the emulation version
And finally, we need to be able to set the emulation version. I've provided two functions for doing this, one which allows you to explicitly set a value, and another that uses the best matching value for the installed version of Internet Explorer.
public static bool SetBrowserEmulationVersion(BrowserEmulationVersion browserEmulationVersion)
{
bool result;
result = false;
try
{
RegistryKey key;
key = Registry.CurrentUser.OpenSubKey(BrowserEmulationKey, true);
if (key != null)
{
string programName;
programName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
if (browserEmulationVersion != BrowserEmulationVersion.Default)
{
// if it's a valid value, update or create the value
key.SetValue(programName, (int)browserEmulationVersion, RegistryValueKind.DWord);
}
else
{
// otherwise, remove the existing value
key.DeleteValue(programName, false);
}
result = true;
}
}
catch (SecurityException)
{
// The user does not have the permissions required to read from the registry key.
}
catch (UnauthorizedAccessException)
{
// The user does not have the necessary registry rights.
}
return result;
}
public static bool SetBrowserEmulationVersion()
{
int ieVersion;
BrowserEmulationVersion emulationCode;
ieVersion = GetInternetExplorerMajorVersion();
if (ieVersion >= 11)
{
emulationCode = BrowserEmulationVersion.Version11;
}
else
{
switch (ieVersion)
{
case 10:
emulationCode = BrowserEmulationVersion.Version10;
break;
case 9:
emulationCode = BrowserEmulationVersion.Version9;
break;
case 8:
emulationCode = BrowserEmulationVersion.Version8;
break;
default:
emulationCode = BrowserEmulationVersion.Version7;
break;
}
}
return SetBrowserEmulationVersion(emulationCode);
}
As mentioned previously, I don't really want these functions
crashing for anticipated reasons, so these functions will also
catch and ignore SecurityException
and
UnauthorizedAccessException
exceptions. The
SetBrowserEmulationVersion
function will return true
if a
value was updated.
Simple Usage
If you just want "fire and forget" updating of the browser emulation version, you can use the following lines.
if (!InternetExplorerBrowserEmulation.IsBrowserEmulationSet())
{
InternetExplorerBrowserEmulation.SetBrowserEmulationVersion();
}
This will apply the best matching IE version if an emulation version isn't set. However, it means if the user updates their copy if IE to something newer, your application will potentially continue to use the older version. I shall leave that as an exercise for another day!
Caveats and points to note
Changing the emulation version while your application is running
While experimenting with this code, I did hit a major caveat.
In the original application this code was written for, I was
applying the emulation version just before the first window
containing a WebBrowser
control was loaded, and this worked
perfectly well.
However, setting the emulation version doesn't seem to work if
an instance of the WebBrowser
control has already been created
in your application. I tried various things such as recreating
the WebBrowser
control or reloading the Form
the control was
hosted on, but couldn't get the new instance to honour the
setting without an application restart.
The attached demonstration program has gone with the "restart after making a selection" hack - please don't do this in production applications!
Should I change the emulation version of my application?
You should carefully consider where or not to change the emulation version of your application. If it's currently working fine, then it's probably better to leave it as is. If however, you wish to make use of modern standards compliant HTML, CSS or JavaScript then setting the appropriate emulation version will save you a lot of trouble.
Further Reading
The are a lot of different options you can apply to Internet
Explorer and the WebBrowser
control. These options allow you
to change behaviours, supported features and quite a few more.
This article has touched upon one of the more common
requirements, but there are a number of other options that are
worth looking at for advanced application scenarios.
An index of all available configuration options can be found on MSDN.
Update History
- 2014-06-28 - First published
- 2020-11-21 - Updated formatting
Downloads
Filename | Description | Version | Release Date | |
---|---|---|---|---|
IeBrowserEmulation.zip
|
Sample file for the article configuring the emulation mode of an Internet Explorer WebBrowser control |
28/06/2014 | Download |
Leave a Comment
While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?
Comments
MAHESH NARAYANAN V V
#
Great...... Its Working Smoothly.... Thank you for your Post
İbrahim Uludağ
#
Very Thanks. Works perferctly.
chris devine
#
the usage command "if (!InternetExplorerBrowserEmulation.IsBrowserEmulationSet()) { InternetExplorerBrowserEmulation.SetBrowserEmulationVersion(); }"
flags the "InternetExplorerBrowserEmulation" as cannot resolve. Could you tell me what am doing wrong. All the other code has no errors
Richard Moss
#
It's the name of the class, so it suggests you've renamed the class to something else. As it's a static method, the class name isn't required, I just prefer it for clarify. Either delete it, or replace it with the name of the class you put the code into.
Salvatore
#
I at all and thanks for your code. It works fine for me but I have a little problem: when my app starts, IE show me a security message about the scripting ("to facilitate the security has been prevented to the file........"). How can I avoid this problem?
ShepSoft
#
Your article is unusual in that it is intelligently written and professionally presented - well done.
An additional (well known) issue with embedded IE is JS pop up errors. If you had time, a mention of this might be a useful extension to your excellent guide - you might mention the idea suggested by Ashot Muradian at http://stackoverflow.com/questions/6138199/wpf-webbrowser-control-how-to-supress-script-errors/18289217#18289217
Thank you.
Tolib Rahimov
#
Great solution! Thank you very much.
mansureh
#
Thank you very much, It helped me
Luis
#
Hey!, thanks for this code, i have a question... all of you tried to show a pdf file inside webbrowser with this code??,.
i cant show a pdf inside of webbrowser, the webbrowser download the file and display on adobe reader desktop app, but without set the emulation mode it shows inside webbrowser.
The Danish
#
This seems to have been fixed in WPF, so instead of using Windows Forms try a WPF project.
Richard Moss
#
I have very little interest in WPF so I haven't tested this, but I do doubt it as the WPF version is the same wrapper. But, as I said, I didn't test so have no idea one way or another. (Also, using WPF to resolve one easily fixed issue is insane ;))
However, I do think that "something" changes with Windows 10, as I tested the example a few weeks back and the
WebBrowser
control appeared to be running in IE11 mode without having to manual specify the emulation mode. I looked at it in a hurry so possibly made a mistake, I do need to recheck that at some point.Regards; Richard Moss
ahmed
#
i got the message " Failed to update browser emulation version ... Why ? and how can resolve it
Richard Moss
#
Hello,
You would find the cause by looking at the coding and debugging it. You can see that the demonstration program will display that message if
Try stepping through the code and see which one it is.
Regards;
Richard Moss
som
#
This demo application is not working for me, js script error message always show for each browser version selection.
Richard Moss
#
Did you try stepping through the sample code to find out why it isn't working?
Christoph Bergner
#
Thank you Richard for the code. Do I understand right that the webbrowser control can only emulate a browser that is installed locally? I have a client who has IE 9 installed on all his machines - would using the webbrowser control emulating IE10 or 11 put him into place to access websites that require a higher version of IE, e.g. in order to use SVG features?
Richard Moss
#
Christoph,
Thanks for the message! Yes, the emulation only works with what is installed, so your IE9 user will not be able to emulate anything higher. You'd either have to upgrade their IE version, or look into embedding a browser into your software that you can control - there are a couple of C# Chrome alternatives, but these come with a hefty size cost. I haven't used these to know how they work or if they are as easy to embed as the
WebBrowser
control.Regards;
Richard Moss
Евгений
#
Thank you so much. My WebBrowser control show me version 11, but I get error. I spend for it all day. After your post it work. Thank you so much again
Richard Moss
#
Glad you found it useful!
Eddy Lai
#
is it possible to make each emulation (IE9, IE10, IE11) use their own session cookie? now they share the same cookie with default Internet Explorer
Richard Moss
#
Hello,
I don't believe this is possible. You can view the feature control registry here; I can't find any mention of configuring the location where cookies are stored so it's probable that this just can't be done.
Regards;
Richard Moss
Javi
#
Good Job!! Thank You
Damo
#
An excellent example, it is what I was looking for. Thank you for both an explanation and the sample! :-)
Justin
#
I've been doing this for a long time now and we recently upgraded to Windows 1809. This now blows up webpages in Outlook. Specifying 11001 or 11000 worked fine on Windows 1607. Now in Windows 1809 the pages act as if I opened IE and am going to the specified webpage using capability settings turned on. This naturally gives a garbled page. I'm wondering if there's new values I have to use above 11000. I can't seem to find official MS documention on this.
Richard Moss
#
Hello,
The documentation is available from here: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330730%28v%3dvs.85%29. It doesn't mention anything about Windows 10, but then it hasn't been updated for years.
I thought Outlook has had its own HTML renderer for many versions now so I'm surprised setting this option for that process would work at all.
Regards;
Richard Moss
Yuli
#
For IE11 in WIN10 you need to look at IE minor version as well. In WIN10 minor version is != 0 while in older OS it's 0. If that's the case, you should set 11001 as the emulation version (BrowserEmulationVersion.Version11Edge).