Deleted
Deleted Member
Post by Deleted on Jun 10, 2015 2:13:55 GMT 10
0
There may be times that a website will report back that your browser version is out of date even-though you have the most current version of Internet Explorer installed. This issue can be observed by navigating your browser application to the site: www.detectmybrowser.com/
How can that be? I have IE11 installed after all.
Some will tell you that it because the control is based on IE6, IE7 or some other out of date browser. This is patently wrong. The .Net WebBrowser (WB) control uses the installed version of Internet Explorer to display its content. The issue is that Microsoft decided that control should default to using the rendering standards of Internet Explorer 7 and this has been the case to date. Webpages can override this behavior by including certain directives to specify which rendering engine to use, but not all do. You can instruct the WB to use a particular rendering version for your application by creating a specific Key in the registry. This registry key must exist before you create an instance of the WB control (more on this later) for it to take effect.
This registry entry can either be created in the "HKEY_LOCAL_MACHINE" (HKLM) hive or in the "HKEY_CURRENT_USER" (HKCU) hive. Using the HKLM hive presents a few issues, the biggest one being that you will need Administrator Privileges to set it and the second one comes into play on 64-bit version of Windows; you have both a 32-bit hive and 64-bit hive to select from. For these reasons, I have chosen to use the current user hive in the code presented below. This particular key is:
\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION
There are two choices for this value for each Internet Explorer version since IE7. The details on these values can be found at: Internet Feature Controls (B..C).
The name of the entry under FEATURE_BROWSER_EMULATION must match your program's name. This becomes a headache during development as your application may be called "WindowsApplication1.exe", but when running under the debugger it is named "WindowsApplication1.vshost.exe". This makes creating the registry keys manually a bit of a pain.
I chose to write this code to use the VB.Net My Namespace to take advantage of the Startup and Shutdown events available to the My.Application object. As I mentioned earlier, the registry key must be set before an instance of the WB control is created and the Startup event is a great way to ensure that happens, but you do not need to use these events if you do not want to. You could create the key in shared constructor of the form that the WB control is on.
I know, quit blah-blahing and show me the code!
VB.NET Code
VB.Net Code:
That is it. Just copy and paste it to a WinForm project and you are good to go. To facilitate the insertion of this code to your project, I have created two "Item Templates" that you can add to your user templates folder. Then you can just add the code from the Project Menu->Insert New Item.
The first will insert the above code.
WebBrowser DocDirective AutoRegistry.zip
The second is one just includes the BrowserSetup class, if you do not want to have the registry key automatically created/deleted.
WebBrowser DocDirective.zip
Do not UnZip these template files; just place the Zip file to your templates folder. Templates are Zip files.
You can find your user templates folder from Tools Menu->Options->Projects and Solutions
For more information see: How to: Locate and Organize Project and Item Templates
If you choose not to have the registry key automatically created/deleted using the Application events, you can do something like the following in your start-up form.
VB.NET Code
hen I wrote my first version of this code a few years ago, I used a Select-Case block to select the proper code to write to the registry. This time I implemented it as a subroutine that loads a dictionary instance.
Code:
This version still suffers the problem that when new versions of Internet Explorer are released this code becomes out of date. However, the subroutine "SetDirectives" can be easily replaced with code that would load the dictionary from a setup file and thereby eliminating the need to recompile the application for each new version of Internet Explorer released. I also have it added logic to select the highest version emulation that it has values for even if it is not the most up to date one available.
How can that be? I have IE11 installed after all.
Some will tell you that it because the control is based on IE6, IE7 or some other out of date browser. This is patently wrong. The .Net WebBrowser (WB) control uses the installed version of Internet Explorer to display its content. The issue is that Microsoft decided that control should default to using the rendering standards of Internet Explorer 7 and this has been the case to date. Webpages can override this behavior by including certain directives to specify which rendering engine to use, but not all do. You can instruct the WB to use a particular rendering version for your application by creating a specific Key in the registry. This registry key must exist before you create an instance of the WB control (more on this later) for it to take effect.
This registry entry can either be created in the "HKEY_LOCAL_MACHINE" (HKLM) hive or in the "HKEY_CURRENT_USER" (HKCU) hive. Using the HKLM hive presents a few issues, the biggest one being that you will need Administrator Privileges to set it and the second one comes into play on 64-bit version of Windows; you have both a 32-bit hive and 64-bit hive to select from. For these reasons, I have chosen to use the current user hive in the code presented below. This particular key is:
\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION
There are two choices for this value for each Internet Explorer version since IE7. The details on these values can be found at: Internet Feature Controls (B..C).
The name of the entry under FEATURE_BROWSER_EMULATION must match your program's name. This becomes a headache during development as your application may be called "WindowsApplication1.exe", but when running under the debugger it is named "WindowsApplication1.vshost.exe". This makes creating the registry keys manually a bit of a pain.
I chose to write this code to use the VB.Net My Namespace to take advantage of the Startup and Shutdown events available to the My.Application object. As I mentioned earlier, the registry key must be set before an instance of the WB control is created and the Startup event is a great way to ensure that happens, but you do not need to use these events if you do not want to. You could create the key in shared constructor of the form that the WB control is on.
I know, quit blah-blahing and show me the code!
VB.NET Code
VB.Net Code:
Namespace My
Partial Friend Class MyApplication
''' <summary>
''' This method is subscribed to the Application.Startup event. This event fires before the
''' main WinForm application begins. For any changes to Internet Explorer's registry settings
''' to be applied to the application, they must be set before the first instance of the browser is created.
'''</summary>
Private Sub _Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
If My.BrowserSetup.DocTypeDirectiveIsAvailable Then
My.BrowserSetup.CreateBrowserKey()
End If
End Sub
Private Sub _Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
If My.BrowserSetup.DocTypeDirectiveIsAvailable Then
My.BrowserSetup.RemoveBrowserKey()
End If
End Sub
End Class 'MyApplication
End Namespace
Namespace My
Partial Friend Class BrowserSetup
Public Shared BrowserMajorVersion As Byte
Public Shared BrowserDirectiveVersion As Byte
Public Shared ReadOnly DocTypeDirectiveIsAvailable As Boolean
Public Shared ReadOnly honorDocTypeDirective As Int32
Public Shared ReadOnly ignoreDocTypeDirective As Int32
Private Shared Directives As New SortedDictionary(Of Byte, BrowserVersionDirective)
Shared Sub New()
BrowserMajorVersion = Version()
SetDirectives()
DocTypeDirectiveIsAvailable = Directives.ContainsKey(BrowserMajorVersion)
If DocTypeDirectiveIsAvailable Then
BrowserDirectiveVersion = BrowserMajorVersion
honorDocTypeDirective = Directives.Item(BrowserMajorVersion).honorDocTypeDirective
ignoreDocTypeDirective = Directives.Item(BrowserMajorVersion).ignoreDocTypeDirective
Else
' use highest version directives available that
For i As Int32 = Directives.Count - 1 To 0 Step -1
If Directives.Keys(i) < BrowserMajorVersion Then
DocTypeDirectiveIsAvailable = True
BrowserDirectiveVersion = Directives.Keys(i)
Dim directive As BrowserVersionDirective = Directives.Values(i)
honorDocTypeDirective = directive.honorDocTypeDirective
ignoreDocTypeDirective = directive.ignoreDocTypeDirective
Exit For
End If
Next
End If
Directives = Nothing
End Sub
Private Shared Function Version() As Byte
Dim wb As New WebBrowser
Dim majorVersion As Int32 = wb.Version.Major
wb.Dispose()
Return CByte(majorVersion)
End Function
''' <summary>Sets Values for IE version 8 thru 11</summary>
Private Shared Sub SetDirectives()
' Value reference: [a href="http://msdn.microsoft.com/en-us/library/ee330730%28v=VS.85%29.aspx"]http://msdn.microsoft.com/en-us/library/ee330730%28v=VS.85%29.aspx[/a]
' !DOCType Reference: [a href="http://msdn.microsoft.com/en-us/library/ms535242%28v=vs.85%29.aspx"]http://msdn.microsoft.com/en-us/library/ms535242%28v=vs.85%29.aspx[/a]
With Directives
.Add(7, New BrowserVersionDirective(7000, 7777))
.Add(8, New BrowserVersionDirective(8000, 8888))
.Add(9, New BrowserVersionDirective(9000, 9999))
.Add(10, New BrowserVersionDirective(10000, 10001))
.Add(11, New BrowserVersionDirective(11000, 11001))
End With
End Sub
Private Class BrowserVersionDirective
Public honorDocTypeDirective As Int16
Public ignoreDocTypeDirective As Int16
Public Sub New(ByVal honorDocTypeDirective As Int16, ByVal ignoreDocTypeDirective As Int16)
Me.honorDocTypeDirective = honorDocTypeDirective
Me.ignoreDocTypeDirective = ignoreDocTypeDirective
End Sub
End Class
#Region "Registry"
Private Const BrowserKeyPath As String = "\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
Friend Shared Sub CreateBrowserKey(Optional ByVal IgnoreDocTypeDirective As Boolean = False)
Dim basekey As String = Microsoft.Win32.Registry.CurrentUser.ToString
Dim value As Int32
Dim thisAppsName As String = My.Application.Info.AssemblyName & ".exe"
If IgnoreDocTypeDirective Then
value = My.BrowserSetup.ignoreDocTypeDirective
Else
value = My.BrowserSetup.honorDocTypeDirective
End If
Microsoft.Win32.Registry.SetValue(Microsoft.Win32.Registry.CurrentUser.ToString & BrowserKeyPath, _
Process.GetCurrentProcess.ProcessName & ".exe", _
value, _
Microsoft.Win32.RegistryValueKind.DWord)
End Sub ' CreateBrowserKey
Friend Shared Sub RemoveBrowserKey()
Dim key As Microsoft.Win32.RegistryKey
key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(BrowserKeyPath.Substring(1), True)
key.DeleteValue(Process.GetCurrentProcess.ProcessName & ".exe", False)
End Sub ' RemoveBrowerKey
#End Region
End Class ' BrowserSetup
End Namespace 'My
That is it. Just copy and paste it to a WinForm project and you are good to go. To facilitate the insertion of this code to your project, I have created two "Item Templates" that you can add to your user templates folder. Then you can just add the code from the Project Menu->Insert New Item.
The first will insert the above code.
WebBrowser DocDirective AutoRegistry.zip
The second is one just includes the BrowserSetup class, if you do not want to have the registry key automatically created/deleted.
WebBrowser DocDirective.zip
Do not UnZip these template files; just place the Zip file to your templates folder. Templates are Zip files.
You can find your user templates folder from Tools Menu->Options->Projects and Solutions
For more information see: How to: Locate and Organize Project and Item Templates
If you choose not to have the registry key automatically created/deleted using the Application events, you can do something like the following in your start-up form.
VB.NET Code
Public Class Form1
Shared Sub New()
My.BrowserSetup.CreateBrowserKey()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
My.BrowserSetup.RemoveBrowserKey()
End Sub
End Class
hen I wrote my first version of this code a few years ago, I used a Select-Case block to select the proper code to write to the registry. This time I implemented it as a subroutine that loads a dictionary instance.
Code:
''' <summary>Sets Values for IE version 8 thru 11</summary>
Private Shared Sub SetDirectives()
' Value reference: http://msdn.microsoft.com/en-us/library/ee330730%28v=VS.85%29.aspx
' !DOCType Reference: http://msdn.microsoft.com/en-us/library/ms535242%28v=vs.85%29.aspx
With Directives
.Add(7, New BrowserVersionDirective(7000, 7777))
.Add(8, New BrowserVersionDirective(8000, 8888))
.Add(9, New BrowserVersionDirective(9000, 9999))
.Add(10, New BrowserVersionDirective(10000, 10001))
.Add(11, New BrowserVersionDirective(11000, 11001))
End With
End Sub
This version still suffers the problem that when new versions of Internet Explorer are released this code becomes out of date. However, the subroutine "SetDirectives" can be easily replaced with code that would load the dictionary from a setup file and thereby eliminating the need to recompile the application for each new version of Internet Explorer released. I also have it added logic to select the highest version emulation that it has values for even if it is not the most up to date one available.
Last Edit: Jun 10, 2015 9:14:14 GMT 10 by Nathan Lecompte