Results 1 to 3 of 3

Thread: Webrowser Version Emulation - Why Is My Browser Reported as IE7?

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Webrowser Version Emulation - Why Is My Browser Reported as IE7?

    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: http://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:
    1. Namespace My
    2.    Partial Friend Class MyApplication
    3.       ''' <summary>
    4.       ''' This method is subscribed to the Application.Startup event.  This event fires before the
    5.       ''' main WinForm application begins.  For any changes to Internet Explorer's registry settings
    6.       ''' to be applied to the application, they must be set before the first instance of the browser is created.            
    7.       '''</summary>
    8.       Private Sub _Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
    9.          If My.BrowserSetup.DocTypeDirectiveIsAvailable Then
    10.             My.BrowserSetup.CreateBrowserKey()
    11.          End If
    12.       End Sub
    13.  
    14.       Private Sub _Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
    15.          If My.BrowserSetup.DocTypeDirectiveIsAvailable Then
    16.             My.BrowserSetup.RemoveBrowserKey()
    17.          End If
    18.       End Sub
    19.    End Class 'MyApplication
    20. End Namespace
    21.  
    22. Namespace My
    23.    Partial Friend Class BrowserSetup
    24.       Public Shared BrowserMajorVersion As Byte
    25.       Public Shared BrowserDirectiveVersion As Byte
    26.       Public Shared ReadOnly DocTypeDirectiveIsAvailable As Boolean
    27.       Public Shared ReadOnly honorDocTypeDirective As Int32
    28.       Public Shared ReadOnly ignoreDocTypeDirective As Int32
    29.  
    30.       Private Shared Directives As New SortedDictionary(Of Byte, BrowserVersionDirective)
    31.  
    32.       Shared Sub New()
    33.          BrowserMajorVersion = Version()
    34.          SetDirectives()
    35.          DocTypeDirectiveIsAvailable = Directives.ContainsKey(BrowserMajorVersion)
    36.          If DocTypeDirectiveIsAvailable Then
    37.             BrowserDirectiveVersion = BrowserMajorVersion
    38.             honorDocTypeDirective = Directives.Item(BrowserMajorVersion).honorDocTypeDirective
    39.             ignoreDocTypeDirective = Directives.Item(BrowserMajorVersion).ignoreDocTypeDirective
    40.          Else
    41.             ' use highest version directives available that
    42.             For i As Int32 = Directives.Count - 1 To 0 Step -1
    43.                If Directives.Keys(i) < BrowserMajorVersion Then
    44.                   DocTypeDirectiveIsAvailable = True
    45.                   BrowserDirectiveVersion = Directives.Keys(i)
    46.                   Dim directive As BrowserVersionDirective = Directives.Values(i)
    47.                   honorDocTypeDirective = directive.honorDocTypeDirective
    48.                   ignoreDocTypeDirective = directive.ignoreDocTypeDirective
    49.                   Exit For
    50.                End If
    51.             Next
    52.          End If
    53.          Directives = Nothing
    54.       End Sub
    55.  
    56.       Private Shared Function Version() As Byte
    57.          Dim wb As New WebBrowser
    58.          Dim majorVersion As Int32 = wb.Version.Major
    59.          wb.Dispose()
    60.          Return CByte(majorVersion)
    61.       End Function
    62.  
    63.       ''' <summary>Sets Values for IE version 8 thru 11</summary>
    64.       Private Shared Sub SetDirectives()
    65.          ' Value reference: [url]http://msdn.microsoft.com/en-us/library/ee330730%28v=VS.85%29.aspx[/url]
    66.          ' !DOCType Reference:  [url]http://msdn.microsoft.com/en-us/library/ms535242%28v=vs.85%29.aspx[/url]
    67.          With Directives
    68.             .Add(7, New BrowserVersionDirective(7000, 7777))
    69.             .Add(8, New BrowserVersionDirective(8000, 8888))
    70.             .Add(9, New BrowserVersionDirective(9000, 9999))
    71.             .Add(10, New BrowserVersionDirective(10000, 10001))
    72.             .Add(11, New BrowserVersionDirective(11000, 11001))
    73.          End With
    74.       End Sub
    75.  
    76.       Private Class BrowserVersionDirective
    77.          Public honorDocTypeDirective As Int16
    78.          Public ignoreDocTypeDirective As Int16
    79.          Public Sub New(ByVal honorDocTypeDirective As Int16, ByVal ignoreDocTypeDirective As Int16)
    80.             Me.honorDocTypeDirective = honorDocTypeDirective
    81.             Me.ignoreDocTypeDirective = ignoreDocTypeDirective
    82.          End Sub
    83.       End Class
    84.  
    85. #Region "Registry"
    86.       Private Const BrowserKeyPath As String = "\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION"
    87.  
    88.       Friend Shared Sub CreateBrowserKey(Optional ByVal IgnoreDocTypeDirective As Boolean = False)
    89.          Dim basekey As String = Microsoft.Win32.Registry.CurrentUser.ToString
    90.          Dim value As Int32
    91.          Dim thisAppsName As String = My.Application.Info.AssemblyName & ".exe"
    92.  
    93.          If IgnoreDocTypeDirective Then
    94.             value = My.BrowserSetup.ignoreDocTypeDirective
    95.          Else
    96.             value = My.BrowserSetup.honorDocTypeDirective
    97.          End If
    98.  
    99.          Microsoft.Win32.Registry.SetValue(Microsoft.Win32.Registry.CurrentUser.ToString & BrowserKeyPath, _
    100.                                            Process.GetCurrentProcess.ProcessName & ".exe", _
    101.                                            value, _
    102.                                            Microsoft.Win32.RegistryValueKind.DWord)
    103.       End Sub ' CreateBrowserKey
    104.  
    105.       Friend Shared Sub RemoveBrowserKey()
    106.          Dim key As Microsoft.Win32.RegistryKey
    107.          key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(BrowserKeyPath.Substring(1), True)
    108.          key.DeleteValue(Process.GetCurrentProcess.ProcessName & ".exe", False)
    109.       End Sub ' RemoveBrowerKey
    110. #End Region
    111.  
    112.    End Class ' BrowserSetup
    113. 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
    Name:  Templates.jpg
Views: 1349
Size:  34.8 KB
    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:
    1. Public Class Form1
    2.    Shared Sub New()
    3.       My.BrowserSetup.CreateBrowserKey()
    4.    End Sub
    5.  
    6.    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    7.       My.BrowserSetup.RemoveBrowserKey()
    8.    End Sub
    9. End Class

    When 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 edited by TnTinMN; Nov 23rd, 2014 at 07:55 PM. Reason: Incorporated BB's comments

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width