以前に別で作成したVBAのChromedriver自動更新プログラムですが色々見直すと実はVBA-JSONなしでも十分ってことに気づいて別途作成しました
条件付きの簡略版ではありますのでご自身の環境に合わせて使い分けてください
やっていること
- chromedriverの保存先は端末環境によって違うので候補となる3箇所のフォルダ有無を確認
- chromeの保存先も端末環境によって違うので候補となる3箇所のフォルダ有無を確認
- PowerShellでchromeのバージョンを取得する
※なので一瞬PowerShellの画面がチラつきます - APIでChrome.exeのビルドまで一致している最新chromedriverのダウンロードパスを取得
- ダウンロードしたzipファイルを解凍してをseleniumbasic用のフォルダへコピーする
以前作成したVBAはJSON API endpointsを総当たりで取得していたのでJSONをパースする必要がありましたが、APIでドライバのバージョンを直接取得できることに気づいて少し手順を簡略化できました
処理としては数秒しか変わりませんがVBA-JSON不要になったのは個人的にGoodポイント
ここからは以前と同じことを書いてますが単独でこのページを見ていただいた方向けです
必要な参照設定
このプログラムを実行するために設定した参照設定

追加したのは下記3つ
- Microsoft Scripting Runtime
- Microsoft XML, v6.0
- Selenium Type Library
ここは旧バージョンと変わりありません
ファイルへの反映手順
サンプルファイルとソースは下部に準備していますがファイルへの反映方法がわからない方向けに反映と使い方です
そんなことわかってるからはよソースを!って方は下部のソースまで飛んじゃってください
プロパティウィンドウを表示しておく
あとからモジュール名を変更したいので、もし表示されていない時は表示しておく
ヘッダーメニュー:表示 → プロパティウィンドウ ※F4がショートカットキー

標準モジュールを追加
自動更新プログラム用にモジュールを追加する
ヘッダーメニュー:挿入 → 標準モジュール

モジュール名を変更する
必須ではないんですが、わかりやすい運用のためにはモジュール名変更推奨です
今回は”ChromeDriverAutoUpdateModule“にします

プログラムの使い方
「<モジュール名>.<プロシージャ名>() ※”<モジュール名>.”は省略可」でプログラムを呼び出せるので、本体プログラムの最初に「ChromeDriverAutoUpdateModule.ChromeDriverAutoUpdate()」を追加すれば必要なときにchromedriverが自動更新されます
Sub main()
'---Chromedriverの自動更新 ※別モジュールを参照
If ChromeDriverAutoUpdateModule.ChromeDriverAutoUpdate Then
Exit Sub
End If
'--・--・--以下にプログラムを--・--・--
End Sub
Chromedriverの書き込み権限がない時
Winsows11からセキュリティ周りが厳しくなったのか管理者権限でSeleniumBasicをインストールした場合、Chromedriverを更新しようとすると書き込み権限なしエラーが発生するので対応まとめました
画像の通りですが下記手順で権限設定ができます
- “C:\Program Files”にある”SeleniumBasic”フォルダを右クリック
- 右クリックメニューで”プロパティ”をクリック
- セキュリティタブに移って”編集”ボタンをクリック
- “Users({コンピュータ名}\Users)”をクリック
- “フルコントロール”にチェックがついていないはずなのでクリックしてチェックを付ける
- “適用”ボタンをクリック

サンプルファイル
JSON-VBA含めて最低限のモジュールをセットしたファイル準備したので一から作る時のベースにしていただければ
最後に実際のソース
まずはGithubをご利用の方向けはこちら
例によってコピペ用はこちらです
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
(ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long
Private Declare PtrSafe Function SHCreateDirectoryEx Lib "shell32.dll" Alias "SHCreateDirectoryExA" _
(ByVal hwnd As LongPtr, ByVal pszPath As String, ByVal psa As LongPtr) As Long
#Else
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
(ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long
Private Declare Function SHCreateDirectoryEx Lib "shell32.dll" Alias "SHCreateDirectoryExA" _
(ByVal hwnd As LongPtr, ByVal pszPath As String, ByVal psa As LongPtr) As Long
#End If
Private Type VersionType '---本当はクラスオブジェクトにしたいけどこれだけのためにモジュール作りたくない
Major As Long
Minor As Long
Build As Long
Revision As Long
BuildVersion As String
RevisionVersion As String
End Type
Const ZIP_FILE As String = "chromedriver.zip"
Const DRIVER_EXE As String = "chromedriver.exe"
Dim workPath As String
Public Function ChromeDriverAutoUpdate(Optional ByVal ForcedExecution As Boolean = False) As Boolean
'====================================================================================================
'chrome.exeとchromedriver.exeのバージョンを比較してchromedriverを自動更新する
'もしくは強制実行フラグ(ForcedExecution)がTrueでも実行する
'====================================================================================================
Dim chromePath As String '---chrome.exeが保存されているパス
Dim chromeFullpath As String '---chrome.exeまで含めたフルパス
Dim chromeVersion As VersionType
Dim chromedriverPath As String
Dim chromedriverFullPath As String
Dim objFso As New Scripting.FileSystemObject
' ---chromedriverをダウンロード用のフォルダを作成する ※Seleniumのキャッシュ構造に合わせている
workPath = Environ("USERPROFILE") & "\.cache\selenium\seleniumbasic"
Select Case SHCreateDirectoryEx(0&, workPath, 0&)
Case 0:
' ---作成成功
Case 183
' ---作成済み
Case Else:
' ---作成できなかった時
MsgBox "ダウンロード用フォルダを作成できませんでした" & vbCrLf & Error(Err), vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End Select
'---chrome本体のフォルダを探す
Select Case True
Case objFso.FolderExists(Environ("ProgramW6432") & "\Google\Chrome\Application")
chromePath = Environ("ProgramW6432") & "\Google\Chrome\Application"
Case objFso.FolderExists(Environ("ProgramFiles") & "\Google\Chrome\Application")
chromePath = Environ("ProgramFiles") & "\Google\Chrome\Application"
Case objFso.FolderExists(Environ("LOCALAPPDATA") & "\Google\Chrome\Application")
chromePath = Environ("LOCALAPPDATA") & "\Google\Chrome\Application"
Case Else
MsgBox "'chrome'フォルダが見つかりません", vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End Select
'---念のためchrome.exeを確認する
If objFso.FileExists(chromePath & "\chrome.exe") = True Then
chromeFullpath = chromePath & "\chrome.exe"
Else
MsgBox "'chrome.exe'が見つかりません", vbCritical
Exit Function
End If
'---SeleniumBasicのフォルダを探す
Select Case True
Case objFso.FolderExists(Environ("ProgramW6432") & "\SeleniumBasic")
chromedriverPath = Environ("ProgramW6432") & "\SeleniumBasic"
Case objFso.FolderExists(Environ("ProgramFiles") & "\SeleniumBasic")
chromedriverPath = Environ("ProgramFiles") & "\SeleniumBasic"
Case objFso.FolderExists(Environ("LOCALAPPDATA") & "\SeleniumBasic")
chromedriverPath = Environ("LOCALAPPDATA") & "\SeleniumBasic"
Case Else
MsgBox "'SeleniumBasic'のフォルダが見つかりません", vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End Select
'---念のためchromedriver.exeを確認する
If objFso.FileExists(chromedriverPath & "\" & DRIVER_EXE) = True Then
chromedriverFullPath = chromedriverPath & "\" & DRIVER_EXE
Else
MsgBox "'chromedriver.exe'が見つかりません", vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End If
'---chrome.exeのバージョンを取得する
If GetChromeVersion(chromeFullpath, chromeVersion) = False Then '---chrome.exeのバージョンを取得する
MsgBox "'chrome.exe'のバージョンが取得できませんでした", vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End If
'---chrome.exeのバージョンに合わせたchromedriver.exeをダウンロードする
If ChromedriverQuickCheck(chromedriverPath, chromeVersion) = False Then '---chromedriverのバージョンを取得する
MsgBox "'chromedriver.exe'のバージョンが取得できませんでした", vbCritical
ChromeDriverAutoUpdate = False
Exit Function
End If
'---結果として更新していない場合もあるが、更新失敗じゃなくて更新不要な判定だからTrueを返す
ChromeDriverAutoUpdate = True
Exit Function
ErrLabel: '---予期せぬエラーの分岐
MsgBox "chromedriver の入替に失敗しました" & vbCrLf & Error(Err) & vbCrLf & "※この画面のキャプチャを作成者へ送ってください"
ChromeDriverAutoUpdate = False
End Function
Private Function GetChromeVersion(ByVal chromeFullpath As String, ByRef chromeVersion As VersionType) As Boolean
'====================================================================================================
'PowerShellでchrome.exeのバージョン情報を取得する ※一瞬PowerShellが立ち上がる
'====================================================================================================
Dim command As String
Dim objRet As Object
On Error GoTo ErrLabel
'---chromeバージョン情報の初期値
chromeVersion.Major = 1
chromeVersion.Minor = 0
chromeVersion.Build = 0
chromeVersion.Revision = 0
'---chrome.exeのバージョンを取得するPowerShellコマンド
command = "powershell.exe -NoProfile -ExecutionPolicy Bypass (Get-Item -Path '" & chromeFullpath & "').VersionInfo.FileVersion"
'---PowerShellの実行結果をセット
Set objRet = CreateObject("WScript.Shell").Exec(command)
'---PowerShellのコマンドレットの実行結果を取得
chromeVersion.RevisionVersion = Trim(objRet.StdOut.ReadAll)
'---情報の取得が終わったらオブジェクトをクリアする
Set objRet = Nothing
'---改行コードが含まれているから削除する
chromeVersion.RevisionVersion = Trim(Replace(Replace(Replace(chromeVersion.RevisionVersion, vbCrLf, vbNullString), vbCr, vbNullString), vbLf, vbNullString))
'---バージョン情報を分けて返す
With CreateObject("VBScript.RegExp") '---正規表現の準備
.Pattern = "\d+\.\d+\.\d+(\.\d+)?"
.Global = True
If .test(chromeVersion.RevisionVersion) Then '---念のため正規表現でバージョン情報をチェックする
chromeVersion.Major = CLng(Split(chromeVersion.RevisionVersion, ".")(0))
chromeVersion.Minor = CLng(Split(chromeVersion.RevisionVersion, ".")(1))
chromeVersion.Build = CLng(Split(chromeVersion.RevisionVersion, ".")(2))
If UBound(Split(chromeVersion.RevisionVersion, ".")) >= 3 Then '---リビジョン番号がなければ9999を仮でセット※基本あるはず
chromeVersion.Revision = CLng(Split(chromeVersion.RevisionVersion, ".")(3))
Else
chromeVersion.Revision = 9999
End If
chromeVersion.BuildVersion = Join(Array(chromeVersion.Major, chromeVersion.Minor, chromeVersion.Build), ".") '---リビジョンを覗いたショートバージョン情報をセットする
Debug.Print "Chromeのバージョン:" & chromeVersion.RevisionVersion
Else '---正規表現不一致なら失敗で返す
MsgBox "chrome.exe のバージョン情報取得に失敗しました" & vbCrLf & "[取得バージョン情報:" & chromeVersion.RevisionVersion & "]" & vbCrLf & "※この画面のキャプチャを作成者へ送ってください"
GetChromeVersion = False
Exit Function
End If
End With
GetChromeVersion = True
On Error GoTo 0
Exit Function
ErrLabel: '---予期せぬエラーの分岐
MsgBox "chrome.exe のバージョン情報取得に失敗しました" & vbCrLf & "[" & Error(Err) & "]" & vbCrLf & "※この画面のキャプチャを作成者へ送ってください"
GetChromeVersion = False
End Function
Private Function ChromedriverQuickCheck(chromedriverPath, chromeVersion As VersionType) As Boolean
Dim objHttp As New MSXML2.XMLHTTP60
Dim targetVarsion As String
Dim uri As String
Dim api_endpoints As String
Dim downloadPath As String
Dim objFso As New Scripting.FileSystemObject
Const TARGET_PLATFORM As String = "win64"
api_endpoints = "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_" & chromeVersion.BuildVersion
On Error GoTo ErrLabel
With objHttp
.Open "GET", api_endpoints, False
.Send
targetVarsion = .responseText '---JSON endpoints から情報を収集する
downloadPath = workPath & "\" & targetVarsion
'--- 念のためリビジョンバージョンを比較する
If chromeVersion.Revision >= CLng(Split(targetVarsion, ".")(3)) Then
'--- まだダウンロードしていなかったらダウンロードする
If objFso.FileExists(downloadPath & "\" & DRIVER_EXE) = False Then
uri = "https://storage.googleapis.com/chrome-for-testing-public/" & targetVarsion & "/" & TARGET_PLATFORM & "/chromedriver-" & TARGET_PLATFORM & ".zip"
Call DownloadChromedriver(uri, targetVarsion)
Call objFso.DeleteFile(chromedriverPath & "\" & DRIVER_EXE, True)
Call objFso.GetFile(downloadPath & "\" & DRIVER_EXE).Copy(chromedriverPath & "\" & DRIVER_EXE, True)
Debug.Print "インストールしたChromedriverのバージョン:" & targetVarsion
Else
Debug.Print "Chromedriverは最新です"
End If
Else
Debug.Print "Chromeのバージョンが古いためChromedriverは更新しません"
End If
End With
On Error GoTo 0
ChromedriverQuickCheck = True
Exit Function
ErrLabel: '---予期せぬエラーの分岐
MsgBox "chromedriver.exe の更新に失敗しました" & vbCrLf & "[" & Error(Err) & "]" & vbCrLf & "※この画面のキャプチャを作成者へ送ってください"
ChromedriverQuickCheck = False
End Function
Private Function DownloadChromedriver(ByVal url As String, targetVersion As String) As Boolean
Dim rc As Long
Dim downloadPath As String
Dim newDriverPath As String
Dim objFso As New Scripting.FileSystemObject
Dim objFolder As Scripting.Folder
downloadPath = workPath & "\" & targetVersion
' ---chromedriverのフォルダを作成する
Select Case SHCreateDirectoryEx(0&, downloadPath, 0&)
Case 0:
' ---作成成功
Case 183
' ---作成済み
Case Else:
' ---作成できなかった時
MsgBox "ChromeDriver用フォルダを作成できませんでした" & vbCrLf & Error(Err), vbCritical
DownloadChromedriver = False
Exit Function
End Select
'---ファイルをダウンロードする
If URLDownloadToFile(0, url, workPath & "\" & ZIP_FILE, 0, 0) <> 0 Then
MsgBox "ChromeDriverをダウンロードできませんでした" & vbCrLf & Error(Err), vbCritical
DownloadChromedriver = False
Exit Function
End If
Application.DisplayAlerts = False
'---zipを既定のフォルダに向けて解凍する
With CreateObject("Shell.Application") '---zipを既定のフォルダに向けて解凍する
.Namespace((downloadPath)).CopyHere .Namespace((workPath & "\" & ZIP_FILE)).Items
End With
'--- 解凍したフォルダから再起処理してchromedriver.exeのフルパスを取得する
newDriverPath = SearchFilesRecursively(downloadPath & "\", "chromedriver.exe")
If newDriverPath = "" Then
MsgBox "chromedriver.exe の更新に失敗しました"
DownloadChromedriver = False
End If
'---chromedriverをバージョンフォルダ直下に移動する
Call objFso.MoveFile(newDriverPath, downloadPath & "\")
'---chromedriverがなくなった不要フォルダを削除する
For Each objFolder In objFso.GetFolder(downloadPath).SubFolders
objFolder.Delete True
Next
'---zipファイルを削除する
Call objFso.DeleteFile(workPath & "\" & ZIP_FILE, True)
Application.DisplayAlerts = True
DownloadChromedriver = True
End Function
Function SearchFilesRecursively(ByVal folderPath As String, fileName As String) As String
'====================================================================================================
' folderPathを起点に再帰処理でサブフォルダまで対象にしてfileNameを探してフルパスを返す
'====================================================================================================
Dim objFso As New Scripting.FileSystemObject
Dim objFolder As Scripting.Folder
Dim subFolder As Scripting.Folder
Dim objFile As Scripting.File
Dim result As String
' ファイル一覧をチェック
For Each objFile In objFso.GetFolder(folderPath).Files
If objFile.Name = fileName Then
SearchFilesRecursively = objFile.Path
Exit Function
End If
Next objFile
' サブフォルダを再帰的に探索
For Each subFolder In objFso.GetFolder(folderPath).SubFolders
result = SearchFilesRecursively(subFolder.Path, fileName)
If result <> "" Then
SearchFilesRecursively = result
Exit Function
End If
Next subFolder
' 見つからなかった場合
SearchFilesRecursively = ""
End Function
あとがき
こちらが後出しなので簡易版としましたがむしろこちらを正規版で過去作成した方を特殊版にした方がいいかなと思っているレベル
今後改修するとしたらこちらになる予定です
コメント