Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WebBrowser IE Emulation for Google Maps JavaScript API Key Requirement

0.00/5 (No votes)
4 Jul 2016 8  
Don't care about Google Maps/Routing/StreetView programming. This Control gives your WinForms applications the power of Google Maps API v3. - my previous article. Unfortunately, since Dec.2015, Google Maps JavaScript API applications requires authentication and the program stopped working properly

Introduction

My Article GMaps v1.1.12 - Google Maps/Routing/StreetView All-in-1 was written in Dec.2014, and worked well. Moreover, the community has awarded it as "Best VB.NET Article of December 2014 (First Prize)". Thanks.

But since Dec.2015, Google Maps JavaScript API applications require authentication, and the program stopped working properly (in "Route" Views, Directions blue line and Text Directions Panel are not shown), because the HTML/JavaScript file runs under the control of the Visual Studio's WebBrowser, which is, by default, Internet Explorer version 7, and that's not enough for the requirements.

Something had to be done. Initially, for my own applications, I got an API Key and proceeded to manual changes in the Registry, etc.

But it was necessary to automate the processes in the aforecited Article's Component, and first I thought to replace the WebBrowser by solutions like Gecko or Awesomium.

In both cases, the implementation of the Engine would cause a much heavier program, and code conversion would be a huge task. So I chose to emulate the WebBrowser to a IE higher version. This involves:

  1. Writing a Value to the Registry Key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
    Instead of HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE could also be used, but that requires high permissions. HKCU is enough.
    The Value is:
    • Value Name: the Name of the Application Project + ".exe" (or ".vshost.exe", if the Project runs inside Visual Studio). Examples:
      MyProgram1.exe
      
      		MyProgram1.vshost.exe
    • Value: a DWORD, as defined here (see Browser Emulation). Values are Decimal. We'll use 11000 (IE 11 default) or 10000 (IE 10 default).
  2. Ensure that the Value is written at the beginning of the Application and deleted when the Application ends (don't fill the Registry with trash).
    The best solution is to use the Startup and Shutdown events of My.Application class, however this cannot be done in a Class Library like the UserControl DLL of the aforementioned article, it's allowed just at WinForms Application level.

Then, and because the DLL Component is written in VB, for any VB Application, instead of using the DLL Component, it's better to insert only one file, GMapsVB.vb (with four classes, including the Component) in the WinForms Project. After rebuilding, the Component will be available in the Toolbox. Hence the reason to write a new Article and not just an Update to the original article.

And for those using other languages (including VB), I also made available a UserControl DLL Project (GMapsX). However, with one limitation: the My.Application Startup and Shutdown events become Methods of the DLL Component and will have to be manually called by the Startup Form events, respectively, Load and [ FormClosing (VB.NET) or OnFormClosing (C#) ].

Prerequisites

  • Visual Studio 2012 or later.
  • To use the new VB Class file or the DLL, the Projects must target to .NET Framework 4 (Client Profile).
  • Internet Explorer 10 or 11 must be installed. In Windows 7, prior to install last IE version, update it to Service Pack 1 (SP1).
  • To acquire full information on the UserControl, see the article GMaps v1.1.12 - Google Maps/Routing/StreetView All-in-1, where you can also download the Documentation. In the present article we will only deal with the differences introduced and the new code.
  • The minimum screen resolution is 1360x768

The Google Maps API Key

The file in which the key has to be placed, which should be present in the executable's Folder, is located in:

...\GMaps_VB\GMapsVB_Demo\GMapsVB_Demo\bin\Release\GMaps1.html , or,

...\GMaps_X\GMapsX_Demo\GMapsX_Demo\bin\Release\GMaps1.html

I don't know the true mechanisms behind the Google Maps API Key, its authentication, its interaction with the Operating System, etc., since the documentation I found, so far, is not very helpful. But the truth is that in most of the machines where I experienced the programs generated by these Projects, everything worked fine with the provided file GMaps1.html, as-is, i.e., without API Key.

"Work fine" means showing Directions blue line and Text Directions Panel in "Route" Views.

Therefore, to start, try running the chosen Project as-is. Works fine? Great!

But if not:

  • Get an API Key here.
  • At the end of file GMaps1.html, find this:
    <!--- (1) First attempt
        <script src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXX"></script>
    --->
    
    <!--- (2) Second attempt
        <script async defer
        src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXX&callback=Init(38.7438882, -9.1417950)">
        </script>
    --->
       
    <!--- Specifying an API KEY (above attempts): --->
    <!--- [(1) or (2)] Replace XXXXXXXXXX by YOUR API KEY --->
    <!--- (2) Replace 38.7438882 by YOUR INITIAL LATITUDE --->
    <!--- (2) Replace -9.1417950 by YOUR INITIAL LONGITUDE --->
    <!--- Uncomment only the chosen <script> ... </script> --->
    
    <!--- (3) Third attempt
          Without loading the API
    --->
  • Make and test the three attempts, in that order, one at a time:
    1. Synchronously loading the API.
    2. Asynchronously loading the API (as reccomended by Google).
    3. Without loading the API (again).

Using the code

1) For GMapsVB, in a new or existing VB Project:
  1. In Solution Explorer -> Application tab -> change the Target framework to .NET Framework 4 (Client Profile is lighter)
  2. Insert the file GMapsVB.vb: Visual Studio Menu PROJECT -> Add Existing Item... -> GMapsVB.vb (select from ...\GMaps_VB\GMapsVB_Demo\GMapsVB_Demo\GMapsVB.vb). By selecting this one, two more files will be transferred: GMapsVB.Designer.vb and GMapsVB.resx
  3. Copy the file GMaps1.html to your Project Startup Folder (...\...\bin\Debug or ...\...\bin\Release, depending on Configuration Manager settings)
  4. Build (or Rebuild) the Project. A new GMapsVB icon will appear in the Toolbox.

GMapsVB.vb contains four Classes:

1) Class GMapsVB - Is the UserControl and therefor must be the first Class.

The only differences to the original v1.1.12 GMaps is that: a) The assembly is not COM-visible, and b) GMaps.html file has changed to GMaps1.html. So the lines

WBrowser.ObjectForScripting = Me
WBrowser.Navigate(Application.StartupPath & "\GMaps.html")

have changed to

' WBrowser.ObjectForScripting = Me
WBrowser.Navigate(Application.StartupPath & "\GMaps1.html")

2) Class MyApplication - Defined within Namespace My

Controls the Startup and Shutdown events, which are raised when the Application starts and ends. Also, contains all the code needed to perform the Emulation operations - Get information, Write and Delete the Registry Key Value. Also calls the _InfoBox Form (defined in the next Class).

  • The CONFIGURATION VARIABLES can be modified, but it is advisable to keep them with the default values until everything works fine.
  • _Process_My_Events - Keep True while Emulation is required (who knows, one day Microsoft can change the WebBrowser defaults...).
  • _Default_Emul_Version - Keep 0, unless there is some advantage in using a previous version.
  • _Verbose_Mode - Change it to False only when everything is OK, i.e., "Route" Views shows the Directions blue line and the Text Directions Panel.
Namespace My
    Partial Friend Class MyApplication
        ' =========================== CONFIGURATION VARIABLES ============================
        Public _Process_My_Events As Boolean = True     ' Events Startup and Shutdown
        Public _Default_Emul_Version As Byte = 0        ' 0 (Installed version), 10, 11
        '                       Only versions 10 or 11 will properly process the HTML file
        Public _Verbose_Mode As Boolean = True          ' True = Shows Form _InfoBox
        ' ================================================================================

Internal variables. Don't change. Meaning of the _InfoBox message's BackColor:

  • Lime: OK. The WebBrowser was emulated for the latest version available.
  • Yellow: Warning. The WebBrowser was emulated for a working version, but not the latest available.
  • Orange: Danger. The WebBrowser was emulated for a (predictably) inadequate version.
  • Red: Error. The WebBrowser was not emulated.
Public OS_64bit As Boolean
Public App_64bit As Boolean
Public RegistryBase As String
Public RegistrySubKey As String
Public ProgName As String
Public IE_Version As String = ""
Public IE_MajorVersion As Byte = 0
Public Emulation As Byte = 0
Public Error_Color As Byte = 3  ' 0=Lime, 1=Yelow, 2=Orange, 3=Red
Public StartupEvent As Boolean

If Startup event has to be processed:

  • GetInfo() collects some info and sets up the internal variables.
  • If no errors are detected, the Registry Key Value is written. Variable Emulation contains a Major Version (i.e., 11, 10,..) and is multiplied by 1000...
  • And (if applicable) the Form _InfoBox is shown.
Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
    If _Process_My_Events Then
        StartupEvent = True
        GetInfo()
        If Error_Color < 3 Then     ' Create Registry Value
            Registry.SetValue(RegistryBase & RegistrySubKey, _
                              ProgName, Emulation * 1000, RegistryValueKind.DWord)
        End If
        ShowInfoBox()
    End If
End Sub

If Shutdown event has to be processed:

  • If the Registry Key Value was written, it is deleted,
  • And (if applicable) the Form _InfoBox is shown.
Private Sub MyApplication_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
    If _Process_My_Events Then
        StartupEvent = False
        If Error_Color < 3 Then     ' Delete Registry Value
            Dim Key As RegistryKey = Registry.CurrentUser.OpenSubKey(RegistrySubKey, True)
            Key.DeleteValue(ProgName)
        End If
        ShowInfoBox()
    End If
End Sub

GetInfo() gets installed IE version and sets some variables, including Emulation (major version to emulate) and Error_Color, which controls the quality of the Action to be taken.

Private Sub GetInfo()
    OS_64bit = Environment.Is64BitOperatingSystem
    App_64bit = Environment.Is64BitProcess
    ' Get Internet Explorer version
    Dim FileIE As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\ieframe.dll"
    If File.Exists(FileIE) Then
        Dim V = FileVersionInfo.GetVersionInfo(FileIE)
        IE_Version = V.ProductVersion
        IE_MajorVersion = V.FileMajorPart
        Error_Color = 0
    End If
    ' Set Registry Base, SubKey and Value Name (EXE program name)
    RegistryBase = Registry.CurrentUser.Name & "\"
    RegistrySubKey = "SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"
    ProgName = My.Application.Info.AssemblyName & If(Debugger.IsAttached, ".vshost", "") & ".exe"

    ' Select IE Emulation version to apply
    If IE_MajorVersion > 0 Then         ' IE detected
        If IE_MajorVersion <= 9 Then    ' Unsuitable version
            Error_Color = 2
        End If
    End If
    If _Default_Emul_Version = 0 OrElse _Default_Emul_Version = IE_MajorVersion Then
        Emulation = IE_MajorVersion
    Else
        If _Default_Emul_Version > IE_MajorVersion OrElse _Default_Emul_Version < 7 Then
            Error_Color = 3
        Else
            Emulation = _Default_Emul_Version
            Error_Color = If(_Default_Emul_Version < 10, 2, 1)
        End If
    End If
End Sub

Form _InfoBox is displayed, when requested, but also when an Error or Danger status was detected.

Private Sub ShowInfoBox()
    If _Verbose_Mode OrElse Error_Color > 1 Then
        Dim F1 As New _InfoBox
        F1.ShowDialog()
        F1.Dispose()
    End If
End Sub
    End Class
End Namespace   ' My

3) Class _InfoBox - Is a Form and has two main blocks: DESIGNER and CODE.

  • DESIGNER is generated by the IDE. Nothing to say about this.
  • CODE prepares the info to show, based on the Internal Variables defined in Class MyApplication, which, within this Class, is visible as Application, of type Friend ReadOnly Property Application, so the variables must be qualified with prefix My.Application.
    Variable .StartupEvent indicates the calling Event: Startup (=True) or Shutdown (=False)
' ============================================================
' ==                          CODE                          ==
' ============================================================

Private Tab_Colors() As Color = {Color.Lime, Color.Yellow, Color.Orange, Color.Red}

Private Sub _InfoBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    With My.Application
        If .StartupEvent Then
            A2.Text = "Startup"
        End If
        If .OS_64bit = False Then
            B2.Text = "32 bits"
        End If
        If .App_64bit = False Then
            C2.Text = "32 bits"
        End If
        D2.Text = .RegistryBase & .RegistrySubKey
        E2.Text = .ProgName
        If .IE_MajorVersion > 0 Then
            F2.Text = .IE_MajorVersion.ToString
            F3.Text = .IE_Version
        End If
        If ._Default_Emul_Version > 0 Then
            G2.Text = ._Default_Emul_Version
        End If
        H2.BackColor = Tab_Colors(.Error_Color)
        If .Error_Color = 3 Then
            H2.ForeColor = Color.Yellow
            If .IE_MajorVersion = 0 Then
                H2.Text = "Internet Explorer not detected..."
            Else
                H2.Text = "Invalid Default version (" & _
                    ._Default_Emul_Version.ToString & ")"
            End If
        Else
            If .StartupEvent Then
                H2.Text &= " " & .Emulation.ToString
            Else
                H2.BackColor = Tab_Colors(0)
                H2.Text = "Registry Value deleted..."
            End If
        End If
    End With
End Sub

Private Sub bClose_Click(sender As Object, e As EventArgs) Handles bClose.Click
    Me.Close()
End Sub

Output examples:

4) Class _List - Is the List Form of the original GMaps UserControl and has two main blocks: DESIGNER and CODE.

  • The only difference is that the Form's Property FormBorderStyle was changed from FixedToolWindow to SizableToolWindow.

Output looks like this:

2) For GMapsX - Other languages (VB inc.):

Project GMapsX produces an UserControl DLL (GMapsX.dll) which must be copied to your Application's Startup Folder and referenced by your WinForms Project.

The file GMaps1.html must also be copied to your Application's Startup Folder.

Compared to GMapsVB, GMapsX only differs in the implementation of Startup and Shutdown events, which can not be defined, as My.Application events, in a Class Library Project. So, Class MyApplication is supressed and the events are to be controlled by the UserControl in Class GMapsX:

1) New Variables are added:

'
' New Public Shared Variables (GMapsX)
'
' =========================== CONFIGURATION VARIABLES ============================
Public Shared _Process_My_Events As Boolean = True     ' Events Startup and Shutdown
Public Shared _Default_Emul_Version As Byte = 0        ' 0 (Installed version), 10, 11
'                       Only versions 10 or 11 will properly process the HTML file
Public Shared _Verbose_Mode As Boolean = True          ' True = Shows Form _InfoBox
' ================================================================================
Public Shared OS_64bit As Boolean
Public Shared App_64bit As Boolean
Public Shared RegistryBase As String
Public Shared RegistrySubKey As String
Public Shared ProgName As String
Public Shared IE_Version As String = ""
Public Shared IE_MajorVersion As Byte = 0
Public Shared Emulation As Byte = 0
Public Shared Error_Color As Byte = 3  ' 0=Lime, 1=Yelow, 2=Orange, 3=Red
Public Shared StartupEvent As Boolean

2) New Properties are created, to allow the change of CONFIGURATION VARIABLES:

'
' New Properties (GMapsX)
'

Public WriteOnly Property Process_My_Events As Boolean
    Set(value As Boolean)
        _Process_My_Events = value
    End Set
End Property

Public WriteOnly Property Default_Emul_Version As Byte
    Set(value As Byte)
        _Default_Emul_Version = value
    End Set
End Property

Public WriteOnly Property Verbose_Mode As Boolean
    Set(value As Boolean)
        _Verbose_Mode = value
    End Set
End Property

3) And the Startup and Shutdown events become Methods (renamed Application_Startup and Application_Shutdown):

'
' New Methods (GMapsX)
'

Public Sub Application_Startup()
    If _Process_My_Events Then
        StartupEvent = True
        GetInfo()
        If Error_Color < 3 Then     ' Create Registry Value
            Registry.SetValue(RegistryBase & RegistrySubKey, _
                              ProgName, Emulation * 1000, RegistryValueKind.DWord)
        End If
        ShowInfoBox()
    End If
End Sub
Public Sub Application_Shutdown()
    If _Process_My_Events Then
        StartupEvent = False
        If Error_Color < 3 Then     ' Delete Registry Value
            Dim Key As RegistryKey = Registry.CurrentUser.OpenSubKey(RegistrySubKey, True)
            Key.DeleteValue(ProgName)
        End If
        ShowInfoBox()
    End If
End Sub
  • Notice that above Methods must be called by the Startup Form events, respectively, Load and [ FormClosing (VB.NET) or OnFormClosing (C#) ]. See examples:
private void Form1_Load(object sender, EventArgs e)
{
    GMapsX1.Process_My_Events = true;   // (Default) - Required to perform Emulation
    GMapsX1.Default_Emul_Version = 0;   // (Default) - Emulates IE installed version
    GMapsX1.Verbose_Mode = true;        // When "Route" views are running OK,
    //                       change to false, to stop displaying InfoBox
    //
    GMapsX1.Application_Startup();      // This is mandatory
}

protected override void OnFormClosing(FormClosingEventArgs e)
{
    GMapsX1.Application_Shutdown();     // This is mandatory
}
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    GMapsX1.Process_My_Events = True ' (Default) - Required to perform Emulation
    GMapsX1.Default_Emul_Version = 0 ' (Default) - Emulates IE installed version
    GMapsX1.Verbose_Mode = True      ' When "Route" views are running OK,
    '                       change to False, to stop displaying InfoBox
    '
    GMapsX1.Application_Startup()    ' This is mandatory
End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    GMapsX1.Application_Shutdown()   ' This is mandatory
End Sub

Placing the Component on the Toolbox

If you right-click the Toolbox -> Choose Items... -> Browse (...\...\GMapsX.dll) -> Open , and you receive a message [ There are no components in '...\...\GmapsX.dll' that can be placed on the toolbox. ], then,

  • With File Explorer, Open the Folder where GMapsX.dll resides.
  • Drag GMapsX.dll and Drop it into the tab (in Toolbox) where you want to place it.

History

04.Jul.2016 - First posted.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here