Jump to content

WDBrowsers - WebDriver Driver Updates


seadoggie01
 Share

Recommended Posts

It seemed like each time I would start up my WebDriver, it would tell me it was out of date. So I wrote some code to auto-download the new Chrome driver when it was out of date.

Now I'm told that my employer will be dropping Chrome and forcing us to use M$ Edge. So I'm back to writing code to auto-download the new driver and I realize how similar these are. I won't be able to test this using other browsers, but I'll add my code here and anyone who wants to add code for other browsers can feel free to as well. 

I know the code is weird and possibly doesn't follow current guidelines, but I'm finding it really interesting for this purpose... it's similar to creating an object oriented interface in AutoIt.

I'll try to add more comments to make the code a bit clearer

Spoiler

WDBrowsers.au3

#include-once

#include <InetConstants.au3>
#include <AutoItConstants.au3>

; A list of supported Browsers
Global Enum $BROWSER_CHROME, _
            $BROWSER_EDGE, _
            $BROWSER_SIZE

; [Internal Use] A list of functions to use
Global Enum $FUNC_BrowserVersion, _
            $FUNC_BrowserPath, _
            $FUNC_DriverDownload, _ ; Unsupported currently, would require a zip extract function
            $FUNC_DriverLatest, _
            $FUNC_DriverVersion, _
            $FUNC_VersionCompatible, _
            $FUNC_Size

; Set your default browser here...
Global $__g_BrowserDefault = $BROWSER_EDGE

; This is where stuff gets interesting...

; This holds a 2-D array of functions that can be accessed through the _WDBrowser_* functions...
;   this approach allows dynamic-ish array sizing and reuse of functions for similar
Global $__g_BrowserFuncs[$BROWSER_SIZE][$FUNC_Size]

; Here, we register all of the browser's functions
__WDBrowser_Register($BROWSER_CHROME, $FUNC_BrowserVersion, __Chromium_BrowserVersion)
__WDBrowser_Register($BROWSER_CHROME, $FUNC_BrowserPath, __Chrome_BrowserPath)
__WDBrowser_Register($BROWSER_CHROME, $FUNC_DriverVersion, __Chromium_DriverVersion)
__WDBrowser_Register($BROWSER_CHROME, $FUNC_DriverLatest, __Chrome_DriverLatest)
__WDBrowser_Register($BROWSER_CHROME, $FUNC_VersionCompatible, __Chrome_VersionCompatible)

__WDBrowser_Register($BROWSER_EDGE, $FUNC_BrowserVersion, __Chromium_BrowserVersion)
__WDBrowser_Register($BROWSER_EDGE, $FUNC_BrowserPath, __Edge_BrowserPath)
__WDBrowser_Register($BROWSER_EDGE, $FUNC_DriverVersion, __Chromium_DriverVersion)
__WDBrowser_Register($BROWSER_EDGE, $FUNC_DriverLatest, __Edge_DriverLatest)
__WDBrowser_Register($BROWSER_EDGE, $FUNC_VersionCompatible, __Edge_VersionCompatible)

; Format of _WDBrowser_* functions...
    ; Create the function with all of the parameters of the internal functions and add $iBrowser = Default
    ; If the browser is default, use the default browser ($__g_BrowserDefault)
    ; Call the actual function that was registered in $__g_BrowserFuncs
    ; Capture the return, error, and extended values and return them all
    #ToDo: Error if function wasn't registered/doesn't exist? 0xDEAD 0xBEEF?

; #FUNCTION# ====================================================================================================================
; Name ..........: _WDBrowser_BrowserPath
; Description ...: Returns the full path to the browser's executable
; Syntax ........: _WDBrowser_BrowserPath([$iBrowser = Default])
; Parameters ....: $iBrowser            - [optional] an integer value. Default is Default.
; Return values .: See internal functions based on $iBrowser
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _WDBrowser_BrowserPath($iBrowser = Default)

    If IsKeyword($iBrowser) Then $iBrowser = $__g_BrowserDefault
    Local $vRet = $__g_BrowserFuncs[$iBrowser][$FUNC_BrowserPath]()
    Return SetError(@error, @extended, $vRet)

EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _WDBrowser_BrowserVersion
; Description ...: Gets the version of the browser
; Syntax ........: _WDBrowser_BrowserVersion($sBrowserPath[, $iBrowser = Default])
; Parameters ....: $sBrowserPath        - a string value.
;                  $iBrowser            - [optional] an integer value. Default is Default.
; Return values .: See internal functions based on $iBrowser
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _WDBrowser_BrowserVersion($sBrowserPath, $iBrowser = Default)

    If IsKeyword($iBrowser) Then $iBrowser = $__g_BrowserDefault
    Local $vRet = $__g_BrowserFuncs[$iBrowser][$FUNC_BrowserVersion]($sBrowserPath)
    Return SetError(@error, @extended, $vRet)

EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _WDBrowser_DriverVersion
; Description ...: Gets the version of the driver
; Syntax ........: _WDBrowser_DriverVersion($sDriverPath[, $iBrowser = Default])
; Parameters ....: $sDriverPath         - a string value.
;                  $iBrowser            - [optional] an integer value. Default is Default.
; Return values .: See internal functions based on $iBrowser
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _WDBrowser_DriverVersion($sDriverPath, $iBrowser = Default)

    If IsKeyword($iBrowser) Then $iBrowser = $__g_BrowserDefault
    Local $vRet = $__g_BrowserFuncs[$iBrowser][$FUNC_DriverVersion]($sDriverPath)
    Return SetError(@error, @extended, $vRet)

EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _WDBrowser_DriverLatest
; Description ...: Gets the latest version of the driver that works with $sBrowserVersion
; Syntax ........: _WDBrowser_DriverLatest($sBrowserVersion[, $iBrowser = Default])
; Parameters ....: $sBrowserVersion     - a string value.
;                  $iBrowser            - [optional] an integer value. Default is Default.
; Return values .: See internal functions based on $iBrowser
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _WDBrowser_DriverLatest($sBrowserVersion, $iBrowser = Default)

    If IsKeyword($iBrowser) Then $iBrowser = $__g_BrowserDefault
    Local $vRet = $__g_BrowserFuncs[$iBrowser][$FUNC_DriverLatest]($sBrowserVersion)
    Return SetError(@error, @extended, $vRet)

EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _WDBrowser_VersionCompatible
; Description ...: Checks if the browser and driver are compatible based on their versions
; Syntax ........: _WDBrowser_VersionCompatible($sBrowserVersion, $sDriverVersion[, $iBrowser = Default])
; Parameters ....: $sBrowserVersion     - a string value.
;                  $sDriverVersion      - a string value.
;                  $iBrowser            - [optional] an integer value. Default is Default.
; Return values .: See internal functions based on $iBrowser
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _WDBrowser_VersionCompatible($sBrowserVersion, $sDriverVersion, $iBrowser = Default)

    If IsKeyword($iBrowser) Then $iBrowser = $__g_BrowserDefault
    Local $vRet = $__g_BrowserFuncs[$iBrowser][$FUNC_VersionCompatible]($sBrowserVersion, $sDriverVersion)
    Return SetError(@error, @extended, $vRet)

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __WDBrowser_Register
; Description ...: Assigns a function to a browser
; Syntax ........: __WDBrowser_Register($iBrowser, $iFunc, $oFunc)
; Parameters ....: $iBrowser            - an integer value.
;                  $iFunc               - an integer value.
;                  $oFunc               - an object.
; Return values .: None
; Author ........: Seadoggie01
; Modified ......: 
; Remarks .......: 
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func __WDBrowser_Register($iBrowser, $iFunc, $oFunc)

    $__g_BrowserFuncs[$iBrowser][$iFunc] = $oFunc

EndFunc

#Region ### Chrome Functions ###

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chrome_BrowserBaseVersion
; Description ...: Strips the ending off of a Chrome version (used to find latest driver versions)
; Syntax ........: __Chrome_BrowserBaseVersion($sChromeVersion)
; Parameters ....: $sChromeVersion      - a string value.
; Return values .: the base browser version
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chrome_BrowserBaseVersion($sChromeVersion)

    Return StringLeft($sChromeVersion, StringInStr($sChromeVersion, ".", 0, -1) - 1)

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chrome_BrowserPath
; Description ...: Gets the full path to the Chrome executable
; Syntax ........: __Chrome_BrowserPath()
; Parameters ....: None
; Return values .: Success - the full path to chrome.exe
;                  Failure - False and sets @error
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chrome_BrowserPath()

    Local $sChromePath = RegRead("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome\InstallLocation", Default)
    If FileExists($sChromePath & "\chrome.exe") Then Return $sChromePath & "\chrome.exe"

    $sChromePath = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome\InstallLocation", Default)
    If FileExists($sChromePath & "\chrome.exe") Then Return $sChromePath & "\chrome.exe"

    $sChromePath = "C:\Program Files (x86)\Google\Chrome\Application\"
    If FileExists($sChromePath & "\chrome.exe") Then Return $sChromePath & "\chrome.exe"

    Return SetError(1, 0, False)

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chrome_DriverLatest
; Description ...: Gets the latest driver version based on the browser version
; Syntax ........: __Chrome_DriverLatest($sBrowserVersion)
; Parameters ....: $sBrowserVersion      - a string value.
; Return values .: Success - the latest driver version
;                  Failure - False, sets @error = 1, sets @extended to InetRead's error
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chrome_DriverLatest($sBrowserVersion)

    ; Read the binary text of the URL
    Local $dVersion = InetRead("https://chromedriver.storage.googleapis.com/LATEST_RELEASE_" & __Chrome_BrowserBaseVersion($sBrowserVersion), $INET_FORCERELOAD)
    If @error Then Return SetError(1, @error, False)

    Return BinaryToString($dVersion)

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chrome_VersionCompatible
; Description ...: Checks if a Chrome browser version is compatible with a driver version
; Syntax ........: __Chrome_VersionCompatible($sBrowserVersion, $sDriverVersion)
; Parameters ....: $sBrowserVersion     - a string value.
;                  $sDriverVersion      - a string value.
; Return values .: Success - True
;                  Failure - False and sets @error:
;                  |0 - Versions aren't compatible
;                  |1 - Error getting latest driver version for the browser version
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chrome_VersionCompatible($sBrowserVersion, $sDriverVersion)

    ; Get the latest version for this chrome version
    Local $sUpdatedDriver = __Chrome_DriverLatest($sBrowserVersion)
    If @error Then Return SetError(1, 0, False)

    ; If the driver versions match
    If $sUpdatedDriver = $sDriverVersion Then Return True

    #ToDo: Optionally, because Chrome browser versions can be compatible with multiple driver versions, check a history of older compatible drivers
    #comments-start
        I do this by storing the values in an Ini file. Like this:
            [Browser Version]
            Driver Version 1-Date compatible 1
            Driver Version 2-Date compatible 2
        Etc...

        Then check with this:
            Return IniRead($sConfig, $sBrowserVersion, $sDriverVersion, -1) <> -1

    #comments-end

    Return False

EndFunc

#EndRegion ### Chrome Functions ###

#Region ### Edge Functions ###

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Edge_BrowserPath
; Description ...: Gets the full path to the Edge executable
; Syntax ........: __Edge_BrowserPath()
; Parameters ....: None
; Return values .: Success - the full path to msedge.exe
;                  Failure - False and sets @error
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Edge_BrowserPath()

    Local $sLikelyPath = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
    If FileExists($sLikelyPath) Then Return $sLikelyPath

    #ToDo: Find other locations
    Return SetError(1, 0, False)

EndFunc

#cs
Func __Edge_DriverDownload($sVersion, $b64 = False)

    Local $sBaseURL = "https://msedgedriver.azureedge.net/"
    $sBaseURL &= $sVersion & "/edgedriver_win"
    If $b64 Then
        $sBaseURL &= "64.zip"
    Else
        $sBaseURL &= "32.zip"
    EndIf

    Local $sZipFile = @UserProfileDir & "\Downloads\edgedriver_win32_" & $sVersion & ".zip"
    InetGet($sBaseURL, $sZipFile)
    If @error Then Return SetError(1, @error, False)

    _Zip_Extract($sZipFile)
    If @error Then Return SetError(2, @error, False)

    Local $sEdgeDriver = StringReplace($sZipFile, ".zip", "\msedgedriver.exe")
    If FileExists($sEdgeDriver) Then Return $sEdgeDriver

    Return SetError(3, 0, False)

EndFunc
#CE

Func __Edge_DriverLatest($sBrowserVersion)

    ; Because Edge browser versions match driver versions, the latest driver for any browser version matches
    Return $sBrowserVersion

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Edge_VersionCompatible
; Description ...: Checks if the Edge browser and driver versions are compatible
; Syntax ........: __Edge_VersionCompatible($sBrowserVersion, $sDriverVersion)
; Parameters ....: $sBrowserVersion     - a string value.
;                  $sDriverVersion      - a string value.
; Return values .: Success - True
;                  Failure - False
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Edge_VersionCompatible($sBrowserVersion, $sDriverVersion)

    Return $sBrowserVersion = $sDriverVersion

EndFunc

#EndRegion ### Edge Functions ###

#Region ### Chromium Functions ###

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chromium_BrowserVersion
; Description ...: Gets the version of the Chromium based browser
; Syntax ........: __Chromium_BrowserVersion($sPath)
; Parameters ....: $sPath               - a string value.
; Return values .: Success - the version string
;                  Failure - False and sets @error to FileGetVersion's error
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chromium_BrowserVersion($sPath)

    Local $vRet = FileGetVersion($sPath)
    Return SetError(@error, @extended, StringStripWS($vRet, 8))

EndFunc

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: __Chromium_DriverVersion
; Description ...: Gets the version of the chromium-based driver
; Syntax ........: __Chromium_DriverVersion($sDriverPath)
; Parameters ....: $sDriverPath         - a string value.
; Return values .: Success - the version string
;                  Failure - False and sets @error:
;                  |1 - $sDriverPath doesn't exist
;                  |2 - Error running --version, sets @extended to Run's error
;                  |3 - Output doesn't match regular expression
; Author ........: Seadoggie01
; Modified ......: September 14, 2020
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __Chromium_DriverVersion($sDriverPath)

    If Not FileExists($sDriverPath) Then Return SetError(1, 0, False)

    Local $sCmd = @ComSpec & ' /c "' & $sDriverPath & '" --version'
    Local $iPid = Run($sCmd, "", @SW_HIDE, $STDOUT_CHILD)
    If @error Then Return SetError(2, 0, False)

    ProcessWaitClose($iPid)

    Local $sOutput = StdoutRead($iPid)

    Local $aVersion = StringRegExp($sOutput, "([\d.]+)", 3)
    If @error Then
        ; Failed to match regex, return the output and an error
        Return SetError(3, 0, $sOutput)
    Else
        ; Return the first continuous set of numbers and periods
        Return $aVersion[0]
    EndIf

EndFunc

#EndRegion ### Chromium Functions ###

 

Edited by seadoggie01
#cs and #CE don't work well online

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

😳

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...