Using Selenium with AutoHotkey- Cross browser automation!

Helpful script writing tricks and HowTo's
User avatar
Sir Teddy the First
Posts: 94
Joined: 05 Aug 2019, 12:31
Contact:

Re: Using Selenium with AutoHotkey- Cross browser automation!

02 Oct 2019, 06:02

Hi all,
I just started with Selenium because I wanted to automate Microsoft Edge.
I installed it to "C:/Programe Files/SeleniumBasic" and the driver for IE is working correctly, but sadly the driver for Edge is not working at all.
I always get a timeout and when I try to start the "edgedriver.exe" I get an error message stating that "the reference number 538 could not be found inside the DLL "edgedriver.exe"".
I already tried updating the windows webdriver to the newest version, but since EdgeHTML version 18 there's no download link anymore, just a command prompt that needs to be executed.
I did that and it said it was succesful, but it's still not working.

Since the SeleniumBasic version is based off version 2.x, is it still possible to get this to work for edge or do I need to somehow update to version 3.x?

Thanks in advance
:eh: :think:
User avatar
Xtra
Posts: 2744
Joined: 02 Oct 2015, 12:15

Re: Using Selenium with AutoHotkey- Cross browser automation!

03 Oct 2019, 15:09

Take a look here: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads
You need a driver that matches the Edge version you are trying to automate. Are you using Microsoft Edge (Chromium)?
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: Using Selenium with AutoHotkey- Cross browser automation!

04 Oct 2019, 10:22

Hello,

there is a way to detect if Chrome was started in debugging mode ( chrome.exe "--remote-debugging-port=9222").
I am currently calling

Code: Select all

ChromeGet()
Msgbox
return


ChromeGet(IP_Port := "127.0.0.1:9222") {
  driver := ComObjCreate("Selenium.ChromeDriver")
  driver.SetCapability("debuggerAddress", IP_Port)
  driver.Start()
  return driver
}
without debugging mode, it takes me a minute to get an error message. Are there other possibilities? The waiting time is too long for me.

Thanks

Bert
gregster
Posts: 8886
Joined: 30 Sep 2013, 06:48

Re: Using Selenium with AutoHotkey- Cross browser automation!

04 Oct 2019, 13:06

Milchmann wrote:
04 Oct 2019, 10:22
without debugging mode, it takes me a minute to get an error message. Are there other possibilities? The waiting time is too long for me.
I haven't used Selenium yet, but I know the chrome debugging protocol a bit.
I would try something like this:

Code: Select all

SetTitleMatchMode, 2
Winwait, Chrome

if CheckforDebugMode()
	driver := ChromeGet()		 ; only executed, if Chrome is in debugging mode
; else [...]
return

CheckforDebugMode(IP_port := "127.0.0.1:9222"){
	http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	http.open("GET", "http://" IP_port "/json")
	try 
		http.send()
	catch
	{ 
		msgbox Chrome is not running in debug mode on this port!
		return false
	}
	return http.responseText
}

ChromeGet(IP_Port := "127.0.0.1:9222") {
  driver := ComObjCreate("Selenium.ChromeDriver")
  driver.SetCapability("debuggerAddress", IP_Port)
  driver.Start()
  return driver
}
User avatar
Sir Teddy the First
Posts: 94
Joined: 05 Aug 2019, 12:31
Contact:

Re: Using Selenium with AutoHotkey- Cross browser automation!

06 Oct 2019, 03:05

@Xtra
I'm using Microsoft Edge (EdgeHTML) version 18 and thats the problem because you can only download the drivers up to version 17, version 18 needs to be installed through the command window so I don't get an .exe-file that I could copy to the SeleniumBasic Folder.
That is my problem.

I already tried downloading the version 17 file. The .exe-file can be started without a problem but when trying to access that driver via AHK I still get a timeout message.
Last edited by Sir Teddy the First on 06 Oct 2019, 10:54, edited 1 time in total.
:eh: :think:
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: Using Selenium with AutoHotkey- Cross browser automation!

06 Oct 2019, 03:42

I haven't used Selenium yet, but I know the chrome debugging protocol a bit.
I would try something like this:
@gregster :

I'll give it a try and give you some feedback.

Thank you
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: Using Selenium with AutoHotkey- Cross browser automation!

08 Oct 2019, 03:22

Hello,

it works great.


Thank you
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Using Selenium with AutoHotkey- Cross browser automation!

08 Oct 2019, 03:37

That still takes seconds to finish the detection if chrome is not running in debug mode. Maybe checking the process command line?

Code: Select all

IsChromeInDebugMode() {
	WinGet, pid, PID, ahk_exe chrome.exe
	if !pid
		throw "Chrome window not found"

	for item in ComObjGet("winmgmts:").ExecQuery("SELECT * FROM Win32_Process WHERE ProcessId='" pid "'")
		if RegExMatch(item.CommandLine, "i)--remote-debugging-port=\K\d+", port)
			return port
}

if !IsChromeInDebugMode()
	MsgBox, 48,, Chrome not in debug mode
gregster
Posts: 8886
Joined: 30 Sep 2013, 06:48

Re: Using Selenium with AutoHotkey- Cross browser automation!

08 Oct 2019, 03:46

Thanks tmplinshi!
You are right, my code may take a few seconds (around 3 here), but I thought that would be better than a minute.
But your approach is more elegant - and faster! :thumbup:

Also thanks for the feedback, Milchmann!
AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: Using Selenium with AutoHotkey- Cross browser automation!

11 Oct 2019, 14:17

Nice Work, tmplinshi I was just looking for a way to detect debugmode some time ago :D .

I combined the functions to have one function (To rule them all) SChrome_Get() to connect to Chrome.
If Chrome was already running in normal mode, it asks if it may restart Chrome.

I am impressed by the speed of selenium, I have a protocol on my work where I webscrape a Web-based Product Data Management (PDM) system(Windchill).
A specific protocol timed 9.4 seconds in IE and 3.5 seconds in Chrome with Selenium, so a nice improvement.

With Xpath it is easy to get elements.
For those who have trouble with Xpath, try to use SChrome_GetElement() to generate the Xpath or just use the function.

Code: Select all

; Written by AHK_User 2019-10-11
; Special thanks to tmplinshi, CH HAN and Joe Glines

SChrome_Get(URL := "", IP_Port := "127.0.0.1:9222"){

	IP_Port_Nr := RegExReplace(IP_Port, ".*:(\d*)", "$1")
	if WinExist("ahk_exe Chrome.exe"){
		WinGet, pid, PID, ahk_exe chrome.exe
		for item in ComObjGet("winmgmts:").ExecQuery("SELECT * FROM Win32_Process WHERE ProcessId='" pid "'"){
			if RegExMatch(item.CommandLine, "i)--remote-debugging-port=\K\d+", port){
				break
			}
		}
		if (Port=""){
			MsgBox, 36, , Is it ok to restart Chrome in debugmode to enable a connection?
			IfMsgBox, Yes
			{
				While(WinExist("ahk_exe chrome.exe")) {
					WinClose, ahk_exe chrome.exe
				}
				Process, WaitClose, chrome.exe
			}
			Else{
				Exit
			}
		}
	}
	
	if(URL!="" or !winExist("ahk_class Chrome_WidgetWin_1")){
		run % "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --remote-debugging-port=" IP_Port_Nr ( winExist("ahk_class Chrome_WidgetWin_1") ? " --new-window " : " " ) URL
	}
	
	Driver := ComObjCreate("Selenium.ChromeDriver")
	Driver.SetCapability("debuggerAddress", IP_Port)
	Driver.Start()
	return Driver
}

SChrome_GetElement(Driver, Value, Type:="id", Tag:="*", Search:="0"){
	;https www.guru99.com /xpath-selenium.html  Broken Link for safety
	if (Tag!=""){
		xPath := "//" Format("{:L}", Tag)
	}
	else {
		xPath := "//*"
	}
	
	if (Search=0){
		xPath .= "["
	}
	else {
		xPath .= "[contains("
	}
	
	if (Type="text"){
		xPath .= "text()"
	}
	else{
		; type: id, name, class,value, href, type, 
		xPath .= "@" Format("{:L}", Type)
	}
	
	if (Search=0){
		xPath .= "=""" Value """]"
	}
	else {
		xPath .= ",""" Value """)]"
	}
	;~ MsgBox, % xPath
	return Driver.findelementbyxpath(xPath)
}

SChrome_SendKey(DriverOrElement, Key){
	;https artoftesting.com /automationTesting/press-enter-tab-space-arrow-function-keys-in-selenium-webdriver-with-java.html  Broken Link for safety
	if (Key="Enter"){
		Key := DriverOrElement.Keys.ENTER
	}
	else if (Key="Escape"){
		Key := DriverOrElement.Keys.ESCAPE
	}
	DriverOrElement.SendKeys(Key) 
	return
}

SChrome_SetElementValue(Driver, Element, Value, Attibute:="value"){
	Driver.executeScript("arguments[0].setAttribute('" Attibute "', '" Value "')", Element)
	return
}

SChrome_RightClick(Driver, Element){
	Driver.Actions.ClickContext(Element).Perform
	return
}

SChrome_Wait(Driver){
; Wait till website is loaded
	Driver.executeScript("return document.readyState").equals("complete") ; wait until page loads
	return
}

SChrome_UpdateDriver(){
	
; Function Updates the Chromedriver by checking the versions and downloading the latest chromedriver.
	
	FileGetVersion, Version_Chrome, C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
	Version_Chrome := RegexReplace(Version_Chrome, "(.*)\.\d\d", "$1")
	
; Get Chromedriver version
	Version_ChromeDriver := RunHide("""C:\Users\" A_UserName "\AppData\Local\SeleniumBasic\chromedriver.exe"" --version")
	Version_ChromeDriver := RegexReplace(Version_ChromeDriver, "[^\d]*([\.\d]*).*", "$1")
	
	;~ DebugWindow("Version Chrome:"  Version_Chrome "`nVersion Chromedriver:" Version_Chromedriver,Clear:=0,LineBreak:=1)
	
; Check if versions are equal
	if InStr(Version_Chromedriver, Version_Chrome){
		MsgBox,68,Testing,Current Chromedriver is same as Chromeversion.`nDo you still want to download?
		IfMsgBox, No 
		{
			exit
		}
	}
	
; Find the matching Chromedriver
	oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	oHTTP.Open("GET", "https chromedriver.storage.googleapis.com /LATEST_RELEASE_"  Broken Link for safety Version_Chrome, true)
	oHTTP.Send()
	oHTTP.WaitForResponse()
	Version_Chromedriver := oHTTP.ResponseText
	
	;~ DebugWindow("The latest release of Chromedriver is:" Version_ChromeDriver,Clear:=0,LineBreak:=1)
	
	if InStr(Version_Chromedriver, "NoSuchKey"){
		MsgBox,16,Testing,Error`nVersion_Chromedriver
		return
	}
	
; Download the Chromedriver
	Url_ChromeDriver := "https chromedriver.storage.googleapis.com /"  Broken Link for safety Version_Chromedriver "/chromedriver_win32.zip"
	URLDownloadToFile, %Url_ChromeDriver%,  %A_ScriptDir%/chromedriver_win32.zip
	
; Unzip Chromedriver_win32.zip
	fso := ComObjCreate("Scripting.FileSystemObject")
	AppObj := ComObjCreate("Shell.Application")
	FolderObj := AppObj.Namespace(A_ScriptDir "\chromedriver_win32.zip")
	FileObj := FolderObj.ParseName("chromedriver.exe")
	AppObj.Namespace(A_ScriptDir "\").CopyHere(FileObj, 4|16)
	
	return
}

RunHide(Command) {
	Run, %ComSpec% /K,, Hide UseErrorLevel, cPid
	
	Process, Wait, %cPid%
	DllCall("AttachConsole", "uint", cPid)
	
	Shell := ComObjCreate("WScript.Shell")
	Exec := Shell.Exec(Command)
	Result := Exec.StdOut.ReadAll()
	
	DllCall("FreeConsole")
	Process, Close, %cPid%
	Return Result
}

burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

14 Oct 2019, 14:44

Thanks very much for this. Would it be possible to have an example with usage for each of the functions?
Regards,
burque505

Edit: Just starting the browser with this script has made life easier. Please see the code in the spoiler for an example, adapted from one of the VBS scripts at the SeleniumBasic github repository. It goes to Startpage.com, searches for "Eiffel Tower" and creates a PDF of the search results, with some text added.
Spoiler
Here's another that's a little hinky, but shows that SeleniumBasic has some sorting capabilities and a

Code: Select all

.ToExcel
function I had no clue existed. That should really come in handy.
Spoiler
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

14 Oct 2019, 16:25

Here's another using PhantomJS, also swiped from the SeleniumBasic examples and modified. I stole AHK_user's "Wait" function also.

Code: Select all

;#Include SChrome_Get.ahk
DetectHiddenWindows, On

addtext =
(
This page was created using a script modified for AutoHotkey from one at
"https://github.com/florentbr/SeleniumBasic/blob/master/Examples/VBScript/CaptureToPdf(PhantomJs).vbs"
It uses some code AHK_user's "SChrome_Get" script, see the Driver_Wait(driver) function,
taken from that script and barely modified.
"https://www.autohotkey.com/boards/viewtopic.php?f=7&t=32323&start=100"
)
driver := ComObjCreate("Selenium.PhantomJSDriver")
driver.get("https://www.startpage.com")
Driver_Wait(driver)

driver.FindElementByXPath("//input[@id='query']").SendKeys("Eiffel Tower")
sleep, 2000
driver.FindElementByXPath("//span[@class='search-form__button-icon']").click()
sleep, 2000

pdf := ComObjCreate("Selenium.PdfFile")

;~ ┌─────────────────────────────────────────┐
;~ │  'Define the PDF page size and margins  │
;~ └─────────────────────────────────────────┘
pdf.SetPageSize(210, 297, "mm")
pdf.SetMargins(5, 5, 5, 15, "mm")

;~ ┌─────────────────────────────────────────┐
;~ │  'Add a title and some text to the PDF  │
;~ └─────────────────────────────────────────┘
pdf.AddTextCenter("Search for Eiffel tower", 18, true)
pdf.AddSpace(10)
pdf.AddText(addtext)

;~ ┌─────────────────────────────────────────────────┐
;~ │  'Open the search page and maximize the window  │
;~ └─────────────────────────────────────────────────┘
driver.Window.Maximize

;~ ┌─────────────────────────────────────────────────────┐
;~ │  'Add a title, the URL and a screenshot to the PDF  │
;~ └─────────────────────────────────────────────────────┘
;~ pdf.AddTitle("Search page")
;~ pdf.AddLink(driver.Url)
;~ pdf.AddImage(driver.TakeScreenshot())


pdf.AddTitle("Results page")
pdf.AddLink(driver.Url)
pdf.AddImage(driver.TakeScreenshot())

;~ ┌───────────────────────────┐
;~ │  'Save the PDF to a file  │
;~ └───────────────────────────┘
pdf.SaveAs("Eiffel Tower search capture.pdf")

Process, Close, ahk_exe phantomjs.exe
driver.Quit    
driver := ""

ExitApp

Driver_Wait(Driver){
; ┌───────────────────────────────┐
; │  Wait till website is loaded  │
; └───────────────────────────────┘
	Driver.executeScript("return document.readyState").equals("complete") ; wait until page loads
	return
}
Probably needs a tooltip to show that things are actually working :D
daiweisc
Posts: 46
Joined: 19 Oct 2019, 04:27

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 01:24

i want to set chrome add_experimental_option ,the aim is download file to save as a new directory :

Code: Select all

driver := ComObjCreate("Selenium.ChromeDriver")           ; Start with Chrome
prefs :="'download.prompt_for_download': True"
driver.AddExperimentalOption("prefs", prefs)
driver.AddArgument("--start-maximized") 
driver.Get("www.***.com")       
but the code is not action , who can help me?
gregster
Posts: 8886
Joined: 30 Sep 2013, 06:48

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 04:57

daiweisc wrote:
25 Oct 2019, 01:24
Just a guess (I can't test it currently):

Code: Select all

driver := ComObjCreate("Selenium.ChromeDriver")          
options := driver.ChromeOptions()		 
prefs := """download.prompt_for_download"": True"		; or prefs := "'download.prompt_for_download': True"
options.AddExperimentalOption("prefs", prefs)
options.AddArgument("--start-maximized")
Question remains, why would this option "download file to save as a new directory" ? Will download.prompt_for_download do that ?
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 05:52

@gregster, did You ever use selenium wrapper for vba? And if Yes, where did You find this methods: AddExperimentalOption, ChromeOptions?
@daiweisc, preferences You can set with WebDriver.SetPreference Method.
gregster
Posts: 8886
Joined: 30 Sep 2013, 06:48

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 09:57

malcev wrote:
25 Oct 2019, 05:52
@gregster, did You ever use selenium wrapper for vba? And if Yes, where did You find this methods: AddExperimentalOption, ChromeOptions?
Well, I wouldn't have called it a guess, if I had so intimate active knowledge, currently. But if you inquire like this, yes, I have used it before (although I always say I haven't), but to be fair, my recollection is a bit foggy, or let's say selective - like most of my memories of the passing decade. 8-)

But many thanks for the correction :salute: By any chance, do you happen to be be acquainted with a good and relevant method reference that you can recommend for the delight and further enlightment of the needy Selenium proletariat, like myself ?
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 10:36

I found only user manual.
gregster
Posts: 8886
Joined: 30 Sep 2013, 06:48

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 11:25

malcev wrote:
25 Oct 2019, 10:36
I found only user manual.
Ok, thanks. Currently , I am still busy checking out the Chrome Debug Protocol via Chrome.ahk. But will come to back to the Selenium manual later.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 11:42

@malcev, there's a couple of places on the web that might qualify as being a user manual. I'd be interested to know which you used, could it be this one?

Thanks!

Regards,
burque505
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Using Selenium with AutoHotkey- Cross browser automation!

25 Oct 2019, 12:05

After installing SeleniumBasic from here:
https://florentbr.github.io/SeleniumBasic/
You will get API documentation of this wrapper in installed directory.
And You can use WebDriver without this wrapper.
Just convert this Autoit library to Autohotkey and use teadrinker JSON parser instead of Coco JSON parser (which is very slow).
https://www.autoitscript.com/forum/topic/191990-webdriver-udf-w3c-compliant-version-9102019/

Return to “Tutorials (v1)”

Who is online

Users browsing this forum: No registered users and 29 guests