在不下载 Selenium 的情况下使用 VBA 自动化 Edge 浏览器
Automating Edge Browser using VBA without downloading Selenium
我有针对 IE 编写的自动化工具。现在,我想通过将“Microsoft Edge”视为默认浏览器来重新编写这些相同的工具。除了下载作为 Selenium 包的一部分的 WebDriver 之外,我找不到其他方法。
有人可以帮助我在没有 downloading/installing 其他软件或 Web 驱动程序的情况下自动化 Edge 浏览器吗?
谢谢,
坎蒂
您可以使用 webdrivermanager 包。因为下面是依赖性:
对于 Maven
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>4.4.3</version>
</dependency>
对于Gradle:
implementation group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.3'
您可以在启动浏览器的 class 中使用以下代码:
WebDriverManager.edgedriver().setup()
您使用的是哪个版本的 Selenium?如果您使用的是 Selenium 3 或 Selenium 4,则可用语言为 Java、Python、C#、Ruby 和 JavaScript。您可以参考this doc了解更多信息。
如果想在VBA中使用Selenium自动化Edge,只能使用SeleniumBasic. You can refer to 使用SeleniumBasic自动化Edge浏览器的详细步骤。
现在有很多方法可以做到这一点。
方法一
自 2022 年 4 月 25 日起,您现在可以使用 VBA 直接自动化 Edge IE 模式,而无需任何额外的第三个 party-software。在与我们合作的 Microsoft 支持团队交流后,我和我的同事对以下指南进行了很好的测试。
你需要做什么
您的 Windows 版本需要至少为 20H2。您可以使用本指南 here.
检查您的 Windows 版本
您的 Windows 需要安装以下 KB:KB5011487。或者简单地更新您的 Windows,这也应该会自动安装。您可以使用本指南 here.
查看您的 Windows 更新历史记录
最后在您的 Windows 上安装以下注册表项并重新启动:
Windows 注册表编辑器版本 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Main]
"NotifyDisableIEOptions"=dword:00000002
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Main\企业模式]
"EnableGlobalWindowListInIEMode"=dword:00000001
根据 MS 支持团队的说法,上述方法应该可以使用到 2029 年。我相信这方面的官方文档可能很快就会发布。
完成上述步骤后,VBA 应该可以像 Internet Explorer window 一样与 Edge IE 模式进行交互了。您当前自动执行 InternetExplorer.Application 对象的代码也将适用于 Edge IE 模式。
方法二
您还可以使用 CodeProject 的 ChrisK23 编写的以下方法,该方法利用 Chrome Devtools 协议与 Chromium-based 浏览器进行交互。这种方式的好处是可以让VBA不用IE模式直接和Edge交互,也可以和Chrome.
交互
Automate Chrome / Edge using VBA via CDP - Code Project
上面的文章还包括一个示例文件,您可以下载该文件并探索该方法。但是,请注意示例文件缺少 Microsoft Scripting Runtime 参考,您需要在之后手动包含它以使其正常工作。
使用此方法,您现在甚至可以 Chrome 自动化,而无需安装其他软件。
方法三
另一种方法涉及使用 winAPI 从 运行ning Edge IE 模式 window.[=16= 的 Internet Explorer Server class 检索 HTML 文档对象]
注意:以上代码适用于 Office 32 位。对于 Office 64 位,您需要转换它们(请参阅此 MSDN link 了解更多详细信息)
这种方法的优点是它非常干净并且与 Edge IE 模式交互良好,无需任何额外的设置或安装。
缺点是仅适用于Edge IE模式。因此,运行 仅在 Edge 而不是 IE 模式下的 Web 应用程序将无法使用此方法实现自动化。此外,就像方法 1 一样,它的寿命取决于 Microsoft 将为 Edge 保留 IE 模式多长时间,目前将持续到 2029 年。除此之外,Microsoft 可能会或可能不再支持 IE 模式。
可以考虑使用WinAPI来实现Edge自动化。它不需要安装和定期更新 Edge 驱动程序。请参阅我在 Edge 浏览器网页自动化上使用 Win API 的经验:
将以下代码放入一个新的空白模块中。我通常将此模块命名为“MsEdge”。该模块中的代码无需修改即可使用。对Win不太了解也可以直接使用代码API.
Public lngProcessID_Close As Long
'Part 1 --- Locate IES
Private strHwndIES As String
Private lngHwndIndex As Long
Private Declare Function EnumWindows Lib "user32" ( _
ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function EnumChildWindows Lib "user32" ( _
ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'Part 2 --- Get HTMLDocument from IES
Private Const SMTO_ABORTIFHUNG = &H2
Private Const GUID_IHTMLDocument2 = "{332C4425-26CB-11D0-B483-00C04FD90119}"
Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" ( _
ByVal lpString As String) As Long
Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" ( _
ByVal hWnd As Long, _
ByVal msg As Long, _
ByVal wParam As Long, _
lParam As Any, _
ByVal fuFlags As Long, _
ByVal uTimeout As Long, _
lpdwResult As Long) As Long
Private Declare Function IIDFromString Lib "ole32" ( _
lpsz As Any, lpiid As Any) As Long
Private Declare Function ObjectFromLresult Lib "oleacc" ( _
ByVal lResult As Long, _
riid As Any, _
ByVal wParam As Long, _
ppvObject As Any) As Long
'Part 3 --- Check Process Name
Private Declare Function GetWindowThreadProcessId Lib "user32" ( _
ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Function findEdgeDOM(Title As String, URL As String) As Object
'Find criteria-hitting Edge page in IE mode
Dim hwndIES As Long
Do
hwndIES = enumHwndIES
If hwndIES Then
Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES)
If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then
Do
hwndIES = enumHwndIES
Loop While hwndIES
Exit Function
Else
Set findEdgeDOM = Nothing
End If
End If
Loop While hwndIES
End Function
Public Function enumHwndIES() As Long
'Get all hwnds of IES
If Len(strHwndIES) = 0 Then
EnumWindows AddressOf EnumWindowsProc, 0
lngHwndIndex = 0
End If
'Exit function when overflow
If lngHwndIndex + 1 > (Len(strHwndIES) - Len(Replace(strHwndIES, ",", ""))) Then
enumHwndIES = 0
strHwndIES = ""
Exit Function
End If
'Return IES hwnd one by one
enumHwndIES = CLng(Split(Left(strHwndIES, Len(strHwndIES) - 1), ",")(lngHwndIndex))
lngHwndIndex = lngHwndIndex + 1
End Function
Private Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
Dim lngProcessID As Long
GetWindowThreadProcessId hWnd, lngProcessID
EnumChildWindows hWnd, AddressOf EnumChildProc, lngProcessID
EnumWindowsProc = True
End Function
Public Function EnumChildProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
Dim strTargetClass As String, strClassName As String
strTargetClass = "Internet Explorer_Server"
strClassName = getClass(hWnd)
If strClassName = strTargetClass Then
If GetObject("winmgmts:").ExecQuery("Select Name from Win32_Process WHERE ProcessId='" & lParam & "' AND Name='msedge.exe'").Count Then
strHwndIES = strHwndIES & hWnd & ","
lngProcessID_Close = lParam
EnumChildProc = False
Exit Function
End If
End If
EnumChildProc = True
End Function
Private Function getClass(hWnd As Long) As String
Dim strClassName As String
Dim lngRetLen As Long
strClassName = Space(255)
lngRetLen = GetClassName(hWnd, strClassName, Len(strClassName))
getClass = Left(strClassName, lngRetLen)
End Function
Public Function getHTMLDocumentFromIES(ByVal hWnd As Long) As Object
Dim iid(0 To 3) As Long
Dim lMsg As Long, lRes As Long
lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT")
SendMessageTimeout hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes
If lRes Then
IIDFromString StrPtr(GUID_IHTMLDocument2), iid(0)
ObjectFromLresult lRes, iid(0), 0, getHTMLDocumentFromIES
End If
End Function
Public Sub closeEdge(Title As String, URL As String)
'Close a Edge browser (the last one in EnumWindows order) with criteria-hitting webpage
lngProcessID_Close = 0
Dim findEdgeDOM As Object
Dim hwndIES As Long
Do
hwndIES = enumHwndIES
If hwndIES Then
Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES)
If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then
Shell "TaskKill /pid " & lngProcessID_Close
Do
hwndIES = enumHwndIES
Loop While hwndIES
Exit Sub
End If
End If
Loop While hwndIES
End Sub
应用“MsEdge”模块中的功能。有几个应用示例供您参考。建议在另一个模块放置和测试以下代码:
Sub findEdgeDOM_DemoProc()
'Demo Proc : Use findEdgeDOM Function to get DOM of specific Edge webpage by Title AND URL
'Dim docHTML As MSHTML.HTMLDocument '--- Early Binding
Dim docHTML As Object '--- Late Binding
Set docHTML = findEdgeDOM("Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here")
‘You can fill just one argument with either part of webpage title or URL as keyword to search for the target browser and leave another one blank (“”). If you provide both title and URL, the funcitons return DOM of the only browser that meets both criteria.
If Not docHTML Is Nothing Then Debug.Print docHTML.Title, docHTML.URL
End Sub
Sub goEdge()
'Go through every Edge webpage (opened in IE mode) and print out hwndIES, webpage Title & webpage URL
Dim hwndIES As Long
'Dim docHTML As MSHTML.HTMLDocument '--- Early Binding
Dim docHTML As Object '--- Late Binding
Do
hwndIES = enumHwndIES
If hwndIES Then
Set docHTML = getHTMLDocumentFromIES(hwndIES)
Debug.Print hwndIES, docHTML.Title, docHTML.URL
Else
Debug.Print "Procedure End"
End If
Loop While hwndIES
End Sub
Sub openEdgeByURL_DemoProc()
'Open Edge browser to specific URL
openEdgeByURL "Input Webpage URL Here"
End Sub
Public Sub openEdgeByURL(URL As String)
'Please change the path to your msedge.exe location in your PC
Shell "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe -url " & URL, vbNormalFocus
End Sub
Sub closeEdge_DemoProc()
'Close Edge browser
closeEdge "Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here"
End Sub
我有针对 IE 编写的自动化工具。现在,我想通过将“Microsoft Edge”视为默认浏览器来重新编写这些相同的工具。除了下载作为 Selenium 包的一部分的 WebDriver 之外,我找不到其他方法。
有人可以帮助我在没有 downloading/installing 其他软件或 Web 驱动程序的情况下自动化 Edge 浏览器吗?
谢谢, 坎蒂
您可以使用 webdrivermanager 包。因为下面是依赖性:
对于 Maven
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>4.4.3</version>
</dependency>
对于Gradle:
implementation group: 'io.github.bonigarcia', name: 'webdrivermanager', version: '4.4.3'
您可以在启动浏览器的 class 中使用以下代码:
WebDriverManager.edgedriver().setup()
您使用的是哪个版本的 Selenium?如果您使用的是 Selenium 3 或 Selenium 4,则可用语言为 Java、Python、C#、Ruby 和 JavaScript。您可以参考this doc了解更多信息。
如果想在VBA中使用Selenium自动化Edge,只能使用SeleniumBasic. You can refer to
现在有很多方法可以做到这一点。
方法一
自 2022 年 4 月 25 日起,您现在可以使用 VBA 直接自动化 Edge IE 模式,而无需任何额外的第三个 party-software。在与我们合作的 Microsoft 支持团队交流后,我和我的同事对以下指南进行了很好的测试。
你需要做什么
您的 Windows 版本需要至少为 20H2。您可以使用本指南 here.
检查您的 Windows 版本您的 Windows 需要安装以下 KB:KB5011487。或者简单地更新您的 Windows,这也应该会自动安装。您可以使用本指南 here.
查看您的 Windows 更新历史记录最后在您的 Windows 上安装以下注册表项并重新启动:
Windows 注册表编辑器版本 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Main] "NotifyDisableIEOptions"=dword:00000002
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Main\企业模式] "EnableGlobalWindowListInIEMode"=dword:00000001
根据 MS 支持团队的说法,上述方法应该可以使用到 2029 年。我相信这方面的官方文档可能很快就会发布。
完成上述步骤后,VBA 应该可以像 Internet Explorer window 一样与 Edge IE 模式进行交互了。您当前自动执行 InternetExplorer.Application 对象的代码也将适用于 Edge IE 模式。
方法二
您还可以使用 CodeProject 的 ChrisK23 编写的以下方法,该方法利用 Chrome Devtools 协议与 Chromium-based 浏览器进行交互。这种方式的好处是可以让VBA不用IE模式直接和Edge交互,也可以和Chrome.
交互Automate Chrome / Edge using VBA via CDP - Code Project
上面的文章还包括一个示例文件,您可以下载该文件并探索该方法。但是,请注意示例文件缺少 Microsoft Scripting Runtime 参考,您需要在之后手动包含它以使其正常工作。
使用此方法,您现在甚至可以 Chrome 自动化,而无需安装其他软件。
方法三
另一种方法涉及使用 winAPI 从 运行ning Edge IE 模式 window.[=16= 的 Internet Explorer Server class 检索 HTML 文档对象]
注意:以上代码适用于 Office 32 位。对于 Office 64 位,您需要转换它们(请参阅此 MSDN link 了解更多详细信息)
这种方法的优点是它非常干净并且与 Edge IE 模式交互良好,无需任何额外的设置或安装。
缺点是仅适用于Edge IE模式。因此,运行 仅在 Edge 而不是 IE 模式下的 Web 应用程序将无法使用此方法实现自动化。此外,就像方法 1 一样,它的寿命取决于 Microsoft 将为 Edge 保留 IE 模式多长时间,目前将持续到 2029 年。除此之外,Microsoft 可能会或可能不再支持 IE 模式。
可以考虑使用WinAPI来实现Edge自动化。它不需要安装和定期更新 Edge 驱动程序。请参阅我在 Edge 浏览器网页自动化上使用 Win API 的经验:
将以下代码放入一个新的空白模块中。我通常将此模块命名为“MsEdge”。该模块中的代码无需修改即可使用。对Win不太了解也可以直接使用代码API.
Public lngProcessID_Close As Long 'Part 1 --- Locate IES Private strHwndIES As String Private lngHwndIndex As Long Private Declare Function EnumWindows Lib "user32" ( _ ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long Private Declare Function EnumChildWindows Lib "user32" ( _ ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _ ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long 'Part 2 --- Get HTMLDocument from IES Private Const SMTO_ABORTIFHUNG = &H2 Private Const GUID_IHTMLDocument2 = "{332C4425-26CB-11D0-B483-00C04FD90119}" Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" ( _ ByVal lpString As String) As Long Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" ( _ ByVal hWnd As Long, _ ByVal msg As Long, _ ByVal wParam As Long, _ lParam As Any, _ ByVal fuFlags As Long, _ ByVal uTimeout As Long, _ lpdwResult As Long) As Long Private Declare Function IIDFromString Lib "ole32" ( _ lpsz As Any, lpiid As Any) As Long Private Declare Function ObjectFromLresult Lib "oleacc" ( _ ByVal lResult As Long, _ riid As Any, _ ByVal wParam As Long, _ ppvObject As Any) As Long 'Part 3 --- Check Process Name Private Declare Function GetWindowThreadProcessId Lib "user32" ( _ ByVal hWnd As Long, lpdwProcessId As Long) As Long Public Function findEdgeDOM(Title As String, URL As String) As Object 'Find criteria-hitting Edge page in IE mode Dim hwndIES As Long Do hwndIES = enumHwndIES If hwndIES Then Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES) If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then Do hwndIES = enumHwndIES Loop While hwndIES Exit Function Else Set findEdgeDOM = Nothing End If End If Loop While hwndIES End Function Public Function enumHwndIES() As Long 'Get all hwnds of IES If Len(strHwndIES) = 0 Then EnumWindows AddressOf EnumWindowsProc, 0 lngHwndIndex = 0 End If 'Exit function when overflow If lngHwndIndex + 1 > (Len(strHwndIES) - Len(Replace(strHwndIES, ",", ""))) Then enumHwndIES = 0 strHwndIES = "" Exit Function End If 'Return IES hwnd one by one enumHwndIES = CLng(Split(Left(strHwndIES, Len(strHwndIES) - 1), ",")(lngHwndIndex)) lngHwndIndex = lngHwndIndex + 1 End Function Private Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean Dim lngProcessID As Long GetWindowThreadProcessId hWnd, lngProcessID EnumChildWindows hWnd, AddressOf EnumChildProc, lngProcessID EnumWindowsProc = True End Function Public Function EnumChildProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean Dim strTargetClass As String, strClassName As String strTargetClass = "Internet Explorer_Server" strClassName = getClass(hWnd) If strClassName = strTargetClass Then If GetObject("winmgmts:").ExecQuery("Select Name from Win32_Process WHERE ProcessId='" & lParam & "' AND Name='msedge.exe'").Count Then strHwndIES = strHwndIES & hWnd & "," lngProcessID_Close = lParam EnumChildProc = False Exit Function End If End If EnumChildProc = True End Function Private Function getClass(hWnd As Long) As String Dim strClassName As String Dim lngRetLen As Long strClassName = Space(255) lngRetLen = GetClassName(hWnd, strClassName, Len(strClassName)) getClass = Left(strClassName, lngRetLen) End Function Public Function getHTMLDocumentFromIES(ByVal hWnd As Long) As Object Dim iid(0 To 3) As Long Dim lMsg As Long, lRes As Long lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT") SendMessageTimeout hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes If lRes Then IIDFromString StrPtr(GUID_IHTMLDocument2), iid(0) ObjectFromLresult lRes, iid(0), 0, getHTMLDocumentFromIES End If End Function Public Sub closeEdge(Title As String, URL As String) 'Close a Edge browser (the last one in EnumWindows order) with criteria-hitting webpage lngProcessID_Close = 0 Dim findEdgeDOM As Object Dim hwndIES As Long Do hwndIES = enumHwndIES If hwndIES Then Set findEdgeDOM = getHTMLDocumentFromIES(hwndIES) If InStr(findEdgeDOM.Title, Title) * InStr(findEdgeDOM.URL, URL) Then Shell "TaskKill /pid " & lngProcessID_Close Do hwndIES = enumHwndIES Loop While hwndIES Exit Sub End If End If Loop While hwndIES End Sub
应用“MsEdge”模块中的功能。有几个应用示例供您参考。建议在另一个模块放置和测试以下代码:
Sub findEdgeDOM_DemoProc() 'Demo Proc : Use findEdgeDOM Function to get DOM of specific Edge webpage by Title AND URL 'Dim docHTML As MSHTML.HTMLDocument '--- Early Binding Dim docHTML As Object '--- Late Binding Set docHTML = findEdgeDOM("Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here") ‘You can fill just one argument with either part of webpage title or URL as keyword to search for the target browser and leave another one blank (“”). If you provide both title and URL, the funcitons return DOM of the only browser that meets both criteria. If Not docHTML Is Nothing Then Debug.Print docHTML.Title, docHTML.URL End Sub Sub goEdge() 'Go through every Edge webpage (opened in IE mode) and print out hwndIES, webpage Title & webpage URL Dim hwndIES As Long 'Dim docHTML As MSHTML.HTMLDocument '--- Early Binding Dim docHTML As Object '--- Late Binding Do hwndIES = enumHwndIES If hwndIES Then Set docHTML = getHTMLDocumentFromIES(hwndIES) Debug.Print hwndIES, docHTML.Title, docHTML.URL Else Debug.Print "Procedure End" End If Loop While hwndIES End Sub Sub openEdgeByURL_DemoProc() 'Open Edge browser to specific URL openEdgeByURL "Input Webpage URL Here" End Sub Public Sub openEdgeByURL(URL As String) 'Please change the path to your msedge.exe location in your PC Shell "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe -url " & URL, vbNormalFocus End Sub Sub closeEdge_DemoProc() 'Close Edge browser closeEdge "Enter Part of Webpage Title Here", "Enter Part of Webpage URL Here" End Sub