Last active
August 20, 2025 13:08
-
-
Save sba923/d5406e7fded598b9c1131ddf9f099564 to your computer and use it in GitHub Desktop.
Update Selenium drivers found on the PATH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # this is one of Stéphane BARIZIEN's public domain scripts | |
| # the most recent version can be found at: | |
| # https://gist.github.com/sba923/d5406e7fded598b9c1131ddf9f099564#file-update-seleniumdriver-ps1 | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(ParameterSetName = 'InstallIfMissing', Mandatory = $true)][switch] $InstallIfMissing, | |
| [Parameter(ParameterSetName = 'InstallIfMissing', Mandatory = $true)][string] $Destination, | |
| [Parameter(ParameterSetName = 'NoParameters')] [switch] $_NeverUseThisParameter, | |
| [switch]$ClearCache | |
| ) | |
| # requires the scripts in https://gist.github.com/sba923/d0d5ad16f2b12d7785adf830b0395dc2 | |
| $seleniummanager = whence -q selenium-manager | |
| if ($null -eq $seleniummanager) | |
| { | |
| throw ("'selenium-manager' not found on PATH") | |
| } | |
| # make sure selenium-manager is the latest version | |
| $tmpfile = Join-Path -Path $env:TEMP -ChildPath 'selenium-manager.exe' | |
| # determine URL for latest production-ready, released selenium-manager.exe | |
| # (see https://github.com/SeleniumHQ/selenium/issues/11694#issuecomment-1927884476) | |
| Write-Verbose("Determining latest version of 'selenium-manager.exe'...") | |
| $url = @(((Invoke-WebRequest -Uri 'https://github.com/SeleniumHQ/selenium/blob/selenium-4.17.0/common/selenium_manager.bzl').Content -split "`n") -match '\.exe' -replace '.*(https://[^"]+selenium-manager-windows\.exe).*', '$1')[0] | |
| Write-Verbose ("Retrieving latest 'selenium-manager.exe' from '{0}'..." -f $url) | |
| Invoke-WebRequest -Uri $url -OutFile $tmpfile | |
| if (!(Test-Path -LiteralPath $tmpfile)) | |
| { | |
| throw ("Cannot retrieve latest 'selenium-manager.exe' from '{0}'" -f $url) | |
| } | |
| if ((Get-FileHash -Path $tmpfile).Hash -ne ((Get-FileHash -Path $seleniummanager).Hash)) | |
| { | |
| Write-Verbose ("Updating '{0}'..." -f $seleniummanager) | |
| Copy-Item -Destination $seleniummanager -Path $tmpfile | |
| } | |
| else | |
| { | |
| Write-Verbose ("'{0}' is already the latest version of 'selenium-manager.exe'" -f $seleniummanager) | |
| } | |
| Remove-Item -Path $tmpfile | |
| Write-Verbose ("Using {0}" -f (selenium-manager --version)) | |
| if ($ClearCache) | |
| { | |
| Remove-Item -Force -Recurse -LiteralPath (Join-Path -Path $env:USERPROFILE -ChildPath ".cache\selenium") -Verbose:($PSBoundParameters.ContainsKey('Verbose')) | |
| } | |
| function ObjectToString($Object, $Prefix = '') | |
| { | |
| if ($Object -is 'Object[]') | |
| { | |
| $string = '' | |
| for ($index = 0; $index -lt $object.Count; $index++) | |
| { | |
| $string += ("`n{2}[{0}]: {1}" -f $index, (ObjectToString -Object $Object[$index] -Prefix ("{0}[{1}]" -f $Prefix, $index)), $Prefix) | |
| } | |
| } | |
| elseif ($Object -is 'PSCustomObject') | |
| { | |
| $string = '' | |
| foreach ($propertyName in $Object.PSObject.Properties.Name) | |
| { | |
| $string += ("`n{0}" -f (ObjectToString -Object $Object.$propertyName -Prefix ($Prefix + '.' + $propertyName))) | |
| } | |
| } | |
| else | |
| { | |
| $string = ("`n{1}:{0}" -f $Object, $Prefix) | |
| } | |
| return ($string -replace '\n{2,}', "`n") | |
| } | |
| # direct download of Selenium driver for Edge when selenium-manager.exe fails to retrieve it | |
| function DownloadEdgeDriver | |
| { | |
| Write-Verbose("Failed to retrieve Selenium driver for '{0}': selenium-manager returned:`n{1}" -f $browser, ((ObjectToString -Object $sm) -replace '^\n+')) | |
| if ($Destination -eq '') | |
| { | |
| $olddriveronpath = whence -q $drivers[$browser] | |
| if ($null -eq $olddriveronpath) | |
| { | |
| $olddriveronpath = whence -q 'MicrosoftWebDriver.exe' | |
| if ($null -eq $olddriveronpath) | |
| { | |
| throw ("'{0}' not found on PATH, cannot determine where to download the new Selenium driver for Edge to" -f $drivers[$browser]) | |
| } | |
| } | |
| $script:Destination = dirname $olddriveronpath | |
| } | |
| $baseUrl = "https://msedgedriver.microsoft.com/" | |
| Write-Verbose("Retrieving the Selenium driver for Edge from {0}" -f $baseUrl) | |
| # Detect installed Edge version | |
| $edgePath = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" | |
| if (-not (Test-Path $edgePath)) | |
| { | |
| throw "Edge executable not found at $edgePath" | |
| } | |
| $edgeVersion = (Get-Item $edgePath).VersionInfo.ProductVersion | |
| Write-Verbose "Detected Edge version: $edgeVersion" | |
| # Construct download URL | |
| $driverZip = "edgedriver_win64.zip" | |
| $driverUrl = "$baseUrl$edgeVersion/$driverZip" | |
| # Test if the driver exists at the URL computed above | |
| try | |
| { | |
| $response = Invoke-WebRequest -Uri $driverUrl -Method Head -ErrorAction Stop | |
| Write-Verbose "WebDriver found for version $edgeVersion" | |
| $null = $response # get rid of PSSA warning | |
| } | |
| catch | |
| { | |
| throw "WebDriver not found for version $edgeVersion. It may not be published yet." | |
| } | |
| $zipPath = Join-Path -Path $env:TEMP -ChildPath $driverZip | |
| # Download and extract | |
| Write-Verbose ("Downloading Selenium driver for Edge from '{0}'..." -f $driverUrl) | |
| Invoke-WebRequest -Uri $driverUrl -OutFile $zipPath | |
| Write-Verbose "Extracting driver..." | |
| Expand-Archive -Path $zipPath -DestinationPath $script:Destination -Force | Out-Null | |
| Remove-Item -LiteralPath $zipPath -Force | |
| Write-Verbose "Selenium driver for Edge downloaded and extracted to: $script:Destination" | |
| } | |
| $drivers = @{ | |
| 'edge' = 'msedgedriver.exe' | |
| 'chrome' = 'chromedriver.exe' | |
| 'firefox' = 'geckodriver.exe' | |
| } | |
| foreach ($browser in $drivers.Keys) | |
| { | |
| Write-Verbose ("Updating Selenium driver '{0}' for browser '{1}'" -f $drivers[$browser], $browser) | |
| $sm = selenium-manager --browser $browser --output JSON | ConvertFrom-JSON | |
| # need to join all lines from selenium-manager's output to account for possible multiple-line output with e.g. WARN | |
| $olddriveronpath = $null | |
| if ($sm.result.code -eq 0) | |
| { | |
| $smdriver = $sm.result.driver_path | |
| $warningitems = @($sm.logs | Where-Object { $_.level -eq 'WARN' }) | |
| if ($warningitems.Count -gt 0) | |
| { | |
| $warnings = $warningitems.message -join "`n" | |
| } | |
| else | |
| { | |
| $warnings = '' | |
| } | |
| if ($warnings -match 'it is advised to delete the driver in PATH and retry') | |
| { | |
| Write-Verbose ("selenium-manager has emitted the 'it is advised to delete the driver in PATH and retry' warning, deleting '{0}' and retrying" -f $sm.result.driver_path) | |
| $olddriveronpath = whence -q $drivers[$browser] | |
| if ($null -eq $olddriveronpath) | |
| { | |
| Write-Host -ForegroundColor Magenta ("selenium-manager warning was unexpected: no {0} on PATH" -f $drivers[$browser]) | |
| } | |
| else | |
| { | |
| Remove-Item -LiteralPath $olddriveronpath -Force -ErrorAction Stop -Verbose:($PSBoundParameters.ContainsKey('Verbose')) | |
| $sm = selenium-manager --browser $browser --output JSON | ConvertFrom-JSON | |
| if ($sm.result.code -ne 0) | |
| { | |
| if ($browser -eq 'edge') | |
| { | |
| DownloadEdgeDriver | |
| } | |
| else | |
| { | |
| throw ("selenium-manager failed: {0}" -f ($sm.logs -join "`n")) | |
| } | |
| } | |
| } | |
| } | |
| elseif ($warnings -match 'error') | |
| { | |
| Write-Verbose ("selenium-manager has emitted a warning with the word 'error', deleting '{0}' and retrying" -f $sm.result.driver_path) | |
| $olddriveronpath = whence -q $drivers[$browser] | |
| if ($null -eq $olddriveronpath) | |
| { | |
| Write-Host -ForegroundColor Magenta ("selenium-manager warning was unexpected: no {0} on PATH" -f $drivers[$browser]) | |
| } | |
| else | |
| { | |
| Remove-Item -LiteralPath $olddriveronpath -Force -ErrorAction Stop -Verbose:($PSBoundParameters.ContainsKey('Verbose')) | |
| $sm = selenium-manager --browser $browser --output JSON | ConvertFrom-JSON | |
| if ($sm.result.code -ne 0) | |
| { | |
| if ($browser -eq 'edge') | |
| { | |
| DownloadEdgeDriver | |
| $smdriver = Join-Path -Path $Destination -ChildPath 'msedgedriver.exe' | |
| } | |
| else | |
| { | |
| throw ("selenium-manager failed: {0}" -f ((ObjectToString -Object $sm) -replace '^\n+')) | |
| } | |
| } | |
| } | |
| } | |
| Write-Verbose ("Selenium driver '{0}' is available" -f $smdriver) | |
| $sdriver = whence -q $drivers[$browser] | |
| if ($null -ne $sdriver) | |
| { | |
| $smdriver_i = Get-Item -LiteralPath $smdriver | |
| $sdriver_i = Get-Item -LiteralPath $sdriver | |
| if (($null -eq $smdriver_i.VersionInfo.FileVersion) -or ($null -eq $sdriver_i.VersionInfo.FileVersion)) | |
| { | |
| if ((Get-FileHash $sdriver_i.FullName).Hash -ne (Get-FileHash $smdriver_i.FullName).Hash) | |
| { | |
| Write-Host -ForegroundColor Yellow ("Updating '{0}' from {1} to {2}" -f $drivers[$browser], $sdriver_i.FullName, $smdriver_i.FullName) | |
| Copy-Item -Verbose -LiteralPath $smdriver -Destination $sdriver | |
| } | |
| else | |
| { | |
| Write-Verbose ("'{0}' is already up to date" -f $sdriver) | |
| } | |
| } | |
| else | |
| { | |
| if ($smdriver_i.VersionInfo.FileVersion -gt $sdriver_i.VersionInfo.FileVersion) | |
| { | |
| Write-Host -ForegroundColor Yellow ("Updating '{0}' from {1} to {2}" -f $drivers[$browser], $sdriver_i.VersionInfo.FileVersion, $smdriver_i.VersionInfo.FileVersion) | |
| Copy-Item -Verbose -LiteralPath $smdriver -Destination $sdriver | |
| } | |
| else | |
| { | |
| Write-Verbose ("'{0}' is already up to date: version {1}" -f $sdriver, $sdriver_i.VersionInfo.FileVersion) | |
| } | |
| } | |
| if ($browser -eq 'edge') | |
| { | |
| $mswebdriver = Join-Path -Path $sdriver_i.Directory -ChildPath 'MicrosoftWebDriver.exe' | |
| if (Test-Path -LiteralPath $mswebdriver) | |
| { | |
| if (Get-Process -Name MicrosoftWebDriver -ErrorAction SilentlyContinue) | |
| { | |
| Stop-Process -name MicrosoftWebDriver -ErrorAction SilentlyContinue | |
| } | |
| } | |
| Copy-Item -Verbose -Destination $mswebdriver -LiteralPath $sdriver | |
| } | |
| } | |
| else | |
| { | |
| if ($InstallIfMissing -or ($null -ne $olddriveronpath)) | |
| { | |
| if ($null -eq $olddriveronpath) | |
| { | |
| $sdriver = Join-Path -Path $Destination -ChildPath $drivers[$browser] | |
| } | |
| else | |
| { | |
| $sdriver = $olddriveronpath | |
| $Destination = Split-Path -Path $olddriveronpath -Parent | |
| } | |
| Write-Host -ForegroundColor Yellow ("Installing '{0}' as '{1}'" -f $drivers[$browser], $sdriver) | |
| Copy-Item -Verbose -LiteralPath $smdriver -Destination $sdriver | |
| if ($browser -eq 'edge') | |
| { | |
| $mswebdriver = Join-Path -Path $Destination -ChildPath 'MicrosoftWebDriver.exe' | |
| if (Test-Path -LiteralPath $mswebdriver) | |
| { | |
| if (Get-Process -Name MicrosoftWebDriver -ErrorAction SilentlyContinue) | |
| { | |
| Stop-Process -name MicrosoftWebDriver -ErrorAction SilentlyContinue | |
| } | |
| } | |
| Copy-Item -Verbose -Destination $mswebdriver -LiteralPath $sdriver | |
| } | |
| } | |
| else | |
| { | |
| Write-Error ("'{0}' not on PATH" -f $drivers[$browser]) | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if ($browser -eq 'edge') | |
| { | |
| DownloadEdgeDriver | |
| } | |
| else | |
| { | |
| Write-Error ("Failed to retrieve Selenium driver for '{0}': selenium-manager returned:`n{1}" -f $browser, ((ObjectToString -Object $sm) -replace '^\n+')) | |
| } | |
| } | |
| } | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-VerboseMicrosoftWebDriver.exeif present alongsidemsedgedriver.exe