Click here to Skip to main content
15,881,678 members
Articles / Programming Languages / Visual Basic

Browser Update for WebBrowser control in VB.NET

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
29 May 2017CPOL3 min read 52.2K   6   11
In this article I will show you how to update WebBrowser control to use the latest installed browser on the host machine.

Introduction

This is a VB.NET class which updates WebBrowser control to use the latest version of the installed browser (Internet Explorer, Edge).

Background

If you need to load a webpage in your VB.NET WinForm or WPF app you have to use a WebBrowser control. The WebBrowser Control is - by default - stuck in IE 7 rendering mode . This happens whether you’re using the WebBrowser control in a WPF application or a WinForms app. You will notice that when your app loads a webpage and page does not look like what you expected! Another case is when you get a message that wants you to update your web browser (IE).

There are a couple of ways to override the default rendering behavior:

  1.     Using the IE X-UA-Compatible Meta header
  2.     Using Application specific FEATURE_BROWSER_EMULATION Registry Keys

If you control the content of the web page, the easiest way to provide latest versions of the IE rendering engine is by using the IE Edge mode header. This is when you apply option 1:

VB.NET
<meta http-equiv="X-UA-Compatible" content="IE=edge" />

You can also specify version of IE:

VB.NET
<meta http-equiv="X-UA-Compatible" content="IE=10" /> 

I will show you how to apply the second method by using a VB.NET calss ( WebBrowserUpdater ) in your code.

Using the code

VB.NET
Public Class WebBrowserUpdater
    Shared is64BitProcess As Boolean = (IntPtr.Size = 8)
    Shared is64BitOperatingSystem As Boolean = is64BitProcess OrElse InternalCheckIsWow64()

    <dllimport("kernel32.dll", callingconvention:="CallingConvention.Winapi)" setlasterror:="True,">_
    Private Shared Function IsWow64Process(<[In]()> ByVal hProcess As IntPtr, <out()> ByRef wow64Process As Boolean) As <marshalas(unmanagedtype.bool)> Boolean
    End Function

    Public Shared Function InternalCheckIsWow64() As Boolean
        If (Environment.OSVersion.Version.Major = 5 AndAlso Environment.OSVersion.Version.Minor >= 1) OrElse Environment.OSVersion.Version.Major >= 6 Then
            Using p As Process = Process.GetCurrentProcess()
                Dim retVal As Boolean
                If Not IsWow64Process(p.Handle, retVal) Then
                    Return False
                End If
                Return retVal
            End Using
        Else
            Return False
        End If
    End Function

    Public Shared Function GetEmbVersion() As Integer
        Dim ieVer As Integer = GetBrowserVersion()

        If ieVer > 9 Then
            Return ieVer * 1000 + 1
        End If

        If ieVer > 7 Then
            Return ieVer * 1111
        End If

        Return 7000
    End Function
    ' End Function GetEmbVersion
    Public Shared Sub FixBrowserVersion()
        Dim appName As String = System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location)
        FixBrowserVersion(appName)
    End Sub

    Public Shared Sub FixBrowserVersion(ByVal appName As String)
        FixBrowserVersion(appName, GetEmbVersion())
    End Sub
    ' End Sub FixBrowserVersion
    Public Shared Sub FixBrowserVersion(ByVal appName As String, ByVal ieVer As Integer)
        FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName & Convert.ToString(".exe"), ieVer)
        FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName & Convert.ToString(".exe"), ieVer)
        FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName & Convert.ToString(".vshost.exe"), ieVer)
        FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName & Convert.ToString(".vshost.exe"), ieVer)
    End Sub
    ' End Sub FixBrowserVersion 
    Private Shared Sub FixBrowserVersion_Internal(ByVal root As String, ByVal appName As String, ByVal ieVer As Integer)
        Try
            'For 64 bit Machine 
            If InternalCheckIsWow64() Then
                Microsoft.Win32.Registry.SetValue(root & Convert.ToString("\Software\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"), appName, ieVer)
            Else
                'For 32 bit Machine 
                Microsoft.Win32.Registry.SetValue(root & Convert.ToString("\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"), appName, ieVer)


            End If
        Catch generatedExceptionName As Exception
            MessageBox.Show("You have to be administrator to run start this process. Please close the software. Right click on the iGiftCard icon and select RUN AS ADMINISTRATOR .", "Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1)
        End Try
    End Sub
    ' End Sub FixBrowserVersion_Internal 
    Public Shared Function GetBrowserVersion() As Integer
        Dim strKeyPath As String = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer"
        Dim ls As String() = New String() {"svcVersion", "svcUpdateVersion", "Version", "W2kVersion"}

        Dim maxVer As Integer = 0
        For i As Integer = 0 To ls.Length - 1
            Dim objVal As Object = Microsoft.Win32.Registry.GetValue(strKeyPath, ls(i), "0")
            Dim strVal As String = System.Convert.ToString(objVal)
            If strVal IsNot Nothing Then
                Dim iPos As Integer = strVal.IndexOf("."c)
                If iPos > 0 Then
                    strVal = strVal.Substring(0, iPos)
                End If

                Dim res As Integer = 0
                If Integer.TryParse(strVal, res) Then
                    maxVer = Math.Max(maxVer, res)
                End If
            End If
        Next
        Return maxVer
    End Function
    ' End Function GetBrowserVersion 

 Since IE 8 Microsoft introduced registry entries that control browser behavior when a WebBrowser Control is embedded into applications. Many applications on your system use these registry values:

Image 1

You can specify a registry with the name of your executable and specify the version of IE that you would like to load. The numbers are specified as 11000, 10000, 9000, 8000 and 7000.

The value specifies the IE version as follows:

The value to set this key to is (taken from MSDN) as decimal values:

11001 (0x2AF9)
Internet Explorer 11. Webpages are displayed in IE11 Standards mode, regardless of the !DOCTYPE directive.

11000 (0x2AF8)
Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

10001 (0x2AF7)
Internet Explorer 10. Webpages are displayed in IE10 Standards mode, regardless of the !DOCTYPE directive.

10000 (0x2710)
Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

9999 (0x270F)
Internet Explorer 9. Webpages are displayed in IE9 Standards mode, regardless of the !DOCTYPE directive.

9000 (0x2328)
Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

8888 (0x22B8)
Webpages are displayed in IE8 Standards mode, regardless of the !DOCTYPE directive.

8000 (0x1F40)
Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode.

7000 (0x1B58)
Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. This mode is kind of pointless since it's the default.

Setting these keys enables your applications to use the latest Internet Explorer versions on the host machine.

WebBrowserUpdater class does what you need in order to run your app by using the latest version of installed IE.

Points of Interest

WebBrowserUpdater has to figure out whether it's dealing with a 32-bit or a 64-bit app. This task is done by the following method:

VB.NET
Public Shared Function InternalCheckIsWow64() As Boolean
    If (Environment.OSVersion.Version.Major = 5 AndAlso Environment.OSVersion.Version.Minor >= 1) OrElse Environment.OSVersion.Version.Major >= 6 Then
        Using p As Process = Process.GetCurrentProcess()
            Dim retVal As Boolean
            If Not IsWow64Process(p.Handle, retVal) Then
                Return False
            End If
            Return retVal
        End Using
    Else
        Return False
    End If
End Function
VB.NET
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

And value setting is done here:

VB.NET
 ' End Sub FixBrowserVersion
Private Shared Sub FixBrowserVersion_Internal(ByVal root As String, ByVal appName As String, ByVal ieVer As Integer)
    Try
        'For 64 bit Machine
        If InternalCheckIsWow64() Then
            Microsoft.Win32.Registry.SetValue(root & Convert.ToString("\Software\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"), appName, ieVer)
        Else
            'For 32 bit Machine
            Microsoft.Win32.Registry.SetValue(root & Convert.ToString("\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"), appName, ieVer)


        End If
    Catch generatedExceptionName As Exception
        MessageBox.Show("You have to be administrator to run start this process. Please close the software. Right click on the iGiftCard icon and select RUN AS ADMINISTRATOR .", "Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1)
    End Try
End Sub

Use this class as shown below:

VB.NET
WebBrowserUpdater.FixBrowserVersion()
VB.NET
WebBrowserUpdater.FixBrowserVersion("AppName")
VB.NET
WebBrowserUpdater.FixBrowserVersion("AppName",IEVer)

Remember that IEVer must be one of the allowed values that I show you before.

Last by not the least. Since we set a registery value, and to avoid any errors, you will need to have elevated privileges in order to apply the changes. Add the following to your app manifist:

VB.NET
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

This code is compatible with .NET 2 through .NET 4.5. If you only use newest versions of .NET in your app then it is possible to shorten the process.

History

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer
United States United States
I sold my beloved racing bicycle to buy my first computer, a Sinclair home computer! That was over 30 years ago and I am still in love with what became my profession, and quite honestly my calling! I have received my BS and MS in Mathematics and Computer science and have been working in so many fields of software development, system architecture, and design and I have most enjoyed teaching and writing about programming languages and fiddling with new technologies!
I believe life is too short to ignore learning a programming language!

Comments and Discussions

 
QuestionHow to detect webbrowser engine ? Pin
jean-paul lamontre14-Jul-22 0:51
jean-paul lamontre14-Jul-22 0:51 
QuestionNot working with my scenrio Pin
evry1falls10-May-20 14:44
evry1falls10-May-20 14:44 
QuestionHere's a better version (and it DOESN'T require administrative status) Pin
Robert Gustafson29-Dec-18 7:02
Robert Gustafson29-Dec-18 7:02 
Nice and simple--and in VB! Here's a better version, though:

Just create the WebBrowserFix class below, and insert the following statement into the Form_Load event of a form that uses a WebBrowser control:

WebBrowserFix.SetBrowserEmulationVersion(My.Application.Info.AssemblyName)

GetCurrentBrowserVersion is for retrieving the user's installed IE version, and SetBrowserEmulationVersion is for changing the IE target version. One overload of the latter method accepts the name of application's assembly and the target version, the other accepts only the target version and uses the name of the last specified assembly. (The shorter overload can only be used after the other overload is used to specify an assembly name; both overloads default to the installed IE version if the version parameter is omitted.)

NOTES:
1) If you class-library the class into a DLL, then name the DLL's root namespace something other than WebBrowserFix--say, WebBrowserFixLibrary. (Otherwise, the above line of code will have to refer the class as "WebBrowserFix.WebBrowserFix" in order to avoid a "Type expected" error.)
2) The methods are all shared, so instantiation of WebBrowserFix isn't required.

My class is as follows:
Imports Microsoft.Win32

''' <summary>
''' This class allows one to configure the WebBrowser control to emulate
''' an arbitrary Internet Explorer version, rather than IE 7 all the time
''' </summary>
Public Class WebBrowserFix

	'   private veriable

	Private Shared wbfAssemblyName As String
	
	'   methods

	''' <summary>
	''' Get current version of Internet Explorer on user's machine
	''' </summary>
	''' <returns>IE version # (throws exception if
	''' IE is not present or pre-version 7)</returns>
	Public Shared Function GetCurrentBrowserVersion() As Integer
		Dim browserVersion As Integer = 0
		'   get version ID
		Using ieKey As RegistryKey = _
				Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Internet Explorer", _
					RegistryKeyPermissionCheck.ReadSubTree, _
					System.Security.AccessControl.RegistryRights.QueryValues)
			Dim version As Object = ieKey.GetValue("svcVersion")
			If version Is Nothing Then
				version = ieKey.GetValue("Version")
				'   no Internet Explorer
				If version Is Nothing Then _
					Throw New ApplicationException("Microsoft Internet Explorer is required!")
			End If
			Integer.TryParse(version.ToString().Split("."c)(0), browserVersion)
		End Using
		'   make sure version is 7 or higher
		If browserVersion < 7 Then
			Throw New ApplicationException("Browser version too low for WebBrowser control!")
		End If
		Return browserVersion
	End Function

	''' <summary>
	''' Set Internet-Explorer emulation mode for most recent application's assembly
	''' </summary>
	''' <param name="browserVersion">Desired IE version to emulate
	''' (defaults current version on user's system if omitted)</param>
	''' <remarks>An exception is thrown if the assembly name wasn't previously
	''' specified, using the other overload for this method</remarks>
	Public Shared Sub SetBrowserEmulationVersion(Optional ByVal browserVersion As Integer = 0)
	'   get name of last assembly specified and set browser version
	WebBrowserFix.SetBrowserEmulationVersion(wbfAssemblyName, browserVersion)
	End Sub

	''' <summary>
	''' Set Internet-Explorer emulation mode for specified application's assembly
	''' </summary>
	''' <param name="AssemblyName">Name of assembly of (parent) application
	''' (an exception is thrownn if null)</param>
	''' <param name="browserVersion">Desired IE version to emulate
	''' (defaults current version on user's system if omitted)</param>
	Public Shared Sub SetBrowserEmulationVersion(ByVal AssemblyName As String, _
		Optional Byval browserVersion As Integer = 0)
	'   get name of current assembly
	If String.IsNullOrEmpty(AssemblyName) Then
		'   not given
		Throw New ApplicationException("Application's assembly name MUST be specified!")
	 Else
		'   save for future calls
		wbfAssemblyName = AssemblyName
	End If
	'   get browser version if not given
	If browserVersion < 1 Then
		browserVersion = WebBrowserFix.GetCurrentBrowserVersion()
	End If
	'   set emulation keys for 32-bit/64-bit release/debug versions
	Registry.SetValue("HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer" _
		& "\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", _
			wbfAssemblyName & ".exe", browserVersion)
	Registry.SetValue("HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer" _
		& "\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", _
			wbfAssemblyName & ".vshost.exe", browserVersion)
	Registry.SetValue("HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\" _
		& "Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", _
			wbfAssemblyName & ".exe", browserVersion)
	Registry.SetValue("HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\" _
		& "Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", _
			wbfAssemblyName & ".vshost.exe", browserVersion)
	End Sub
End Class

I plan to post this code as a DLL (with a demo app) as an "alternative version" soon. Note that my version of the class (when one excludes comments) uses a lot less code, and doesn't require an end user to run the app "as administer" since it uses HEY_CURRENT_USER rather than HKEY_LOCAL_MACHINE as the registry root for changes!

modified 1-Jan-19 8:53am.

AnswerRe: Here's a better version (and it DOESN'T require administrative status) Pin
Domesoft8-Feb-23 7:14
Domesoft8-Feb-23 7:14 
QuestionError in InternalCheckIsWow64 Pin
Pushaw2-Aug-18 9:13
Pushaw2-Aug-18 9:13 
AnswerRe: Error in InternalCheckIsWow64 Pin
Jens Madsen, Højby5-Sep-18 12:24
Jens Madsen, Højby5-Sep-18 12:24 
QuestionHow to use it? Pin
ADemontis1-Apr-18 3:54
professionalADemontis1-Apr-18 3:54 
AnswerRe: How to use it? Pin
Robert Gustafson29-Dec-18 7:44
Robert Gustafson29-Dec-18 7:44 
PraiseMy Vote of Five Pin
Alan Burkhart15-Jul-17 4:18
Alan Burkhart15-Jul-17 4:18 
Suggestionpretty useful Pin
loyal ginger31-May-17 2:56
loyal ginger31-May-17 2:56 
GeneralRe: pretty useful Pin
Member 1235231513-Nov-17 5:07
Member 1235231513-Nov-17 5:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.