[Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post your working scripts, libraries and tools
malcev
Posts: 1015
Joined: 12 Aug 2014, 12:37

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by malcev » 22 Mar 2021, 16:33

I do not recommend to use slow and buggy coco json parser and do not understand why GeekDude uses it.

Code: Select all

global PageInst
PageInst := ChromeInst.GetPage(,,"callback")
PageInst.Call("Page.enable")
return

callback(event)																				
{
   if (event.method = "Page.javascriptDialogOpening")
      PageInst.Call("Page.handleJavaScriptDialog", {"accept": LightJson.true}, false)
}

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 24 Mar 2021, 12:21

Nice, @malcev thank you. Below is working code for @AHK_user's page using your code above. No doubt has bugs, redundancies and other overkill but works.
I can never find @teadrinker's Chrome.ahk when I search the forum so it's attached as well for those who may find it useful. I use it as 'tdChrome.ahk in this script.

Code: Select all

#Include tdChrome.ahk
SetTitleMatchMode, 2
;FileCreateDir, ChromeProfile


ChromeInst := new Chrome("ChromeProfile")
Sleep, 3000
PageInstance := ChromeInst.GetPage()
PageInstance.Call("Page.navigate", {"url": "https://the-internet.herokuapp.com/javascript_alerts"})
PageInstance.WaitForLoad()
sleep, 3000


global PageInst
PageInst := ChromeInst.GetPage(,,"callback")
PageInst.Call("Page.enable")

PageInstance.Evaluate("document.querySelector(""button[onclick='jsAlert()']"").click();")


; ┌─────────────────────────┐
; │  Close Browser routine  │
; └─────────────────────────┘

msgbox, ,Exiting, Exiting script, 2
PageInstance.Call("Browser.close")


PageInstance.Disconnect()
PageInstance := ""
ChromeInst := ""
ChromeInstance.Kill()
WinKill, chrome.exe

; Kill conhost.exe so it doesn't hang around.
; 
DetectHiddenWindows, On
; From GeekDude's tips and tricks: https://www.autohotkey.com/boards/viewtopic.php?f=7&t=7190
Run, cmd,, Hide, PID
WinWait, ahk_pid %PID%
DllCall("AttachConsole", "UInt", PID)

; Run another process that would normally
; make a command prompt pop up, such as
; RunWait, cmd /c dir > PingOutput.txt
Runwait, taskkill /im conhost.exe /f 
; Thanks to @flyingDman post from 2010, 
; https://autohotkey.com/board/topic/49732-kill-process/

; Close the hidden command prompt process
Process, Close, %PID%
ExitApp

callback(event)																				
{
   if (event.method = "Page.javascriptDialogOpening") {
      sleep, 3000
      PageInst.Call("Page.handleJavaScriptDialog", {"accept": LightJson.true}, false)
   }
}


/* new malcev code
global PageInst
PageInst := ChromeInst.GetPage(,,"callback")
PageInst.Call("Page.enable")
return

callback(event)																				
{
   if (event.method = "Page.javascriptDialogOpening")
      PageInst.Call("Page.handleJavaScriptDialog", {"accept": LightJson.true}, false)
}

*/
Regards,
burque505
Attachments
tdChrome.ahk
(16.37 KiB) Downloaded 50 times

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 24 Mar 2021, 12:36

Ever notice how you can go browsing through the AHK forums and go off on a completely unexpected tangent? Maybe it's just me but I doubt it seriously.
Now that I've got Chrome.ahk in my head (it will leave soon I'm sure), I thought I'd share this code that sets a custom download folder, creates a blob with the text of a webpage element in it, and then downloads that blob to a named file on my system. I'm using @teadrinker's tdChrome.ahk (see post above), which as an interesting side effect lets Chrome preserve that notification (bottom left in the Chrome window) about the downloaded file.

Code: Select all

#Include tdChrome.ahk
SetTitleMatchMode, 2
;FileCreateDir, ChromeProfile
SetBatchLines, -1

;****************
; Fix these paths for your system
; or the world will explode
; without notice
;****************
dlPath := "C:\ResearchDownloads\Testing"
If (FileExist("C:\ResearchDownloads\Testing\abc.txt"))
	FileDelete, C:\ResearchDownloads\Testing\abc.txt
webpage := "https://www.autohotkey.com"
ChromeInst := new Chrome("ChromeProfile")

Sleep, 3000
PageInstance := ChromeInst.GetPage()
PageInstance.WaitForLoad()
WinMaximize, ahk_exe chrome.exe
PageInstance.Call("Page.navigate", {"url": webpage})

;****************
; Make Chrome download to a specific directory
; @gregster mentions this at https://www.autohotkey.com/boards/viewtopic.php?f=76&t=77637&hilit=page.setdownloadbehavior
; I didn't see that till after I tried this, my syntax is marginally different (quotes around behavior and downloadPath)
; Works both ways.
;****************
PageInstance.Call("Page.setDownloadBehavior", {"behavior" : "allow", "downloadPath": dlPath})
PageInstance.WaitForLoad()

;****************
; This JS will grab the innerHTML of title at autohotkey.com, set the mime_type,
; create a blob of mime_type (i.e. text), create a hidden anchor, set the href
; of the anchor to the blob location, 
; grab the href of that blob, stringify it, 
; alert with the stringified href, download the blob as 'abc.txt' to the
; custom download directory in 'dlPath'.
;****************
js =
(
var myData = document.getElementById("MainTitle").innerHTML
var mime_type = "text/plain";
var blob = new Blob([myData], {type: mime_type});
let hidden = document.createElement('a');
hidden.href = window.URL.createObjectURL(blob);
var stringy = hidden.href.toString();
alert(stringy);
hidden.download = 'abc.txt';
hidden.click();
hidden.remove();
)
PageInstance.Evaluate(js)

;~ A search for 'window.URL.createObjectURL(blob)'
;~ may be useful to you.

Sleep, 10000
PageInstance.Call("Browser.close")
ChromeInst.Disconnect()

PageInstance.Disconnect()

; Overkill, no doubt. Works.
PageInstance := ""
ChromeInst := ""
ChromeInstance.Kill()
WinKill, chrome.exe

; Kill conhost.exe so it doesn't hang around.
; 
DetectHiddenWindows, On
; From GeekDude's tips and tricks: https://www.autohotkey.com/boards/viewtopic.php?f=7&t=7190
Run, cmd,, Hide, PID
WinWait, ahk_pid %PID%
DllCall("AttachConsole", "UInt", PID)

; Run another process that would normally
; make a command prompt pop up, such as
; RunWait, cmd /c dir > PingOutput.txt
Runwait, taskkill /im conhost.exe /f 
; Thanks to @flyingDman post from 2010, 
; https://autohotkey.com/board/topic/49732-kill-process/

; Close the hidden command prompt process
Process, Close, %PID%
ExitApp

Regards,
burque505

AHK_user
Posts: 102
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by AHK_user » 24 Mar 2021, 14:13

burque505 wrote:
24 Mar 2021, 12:21
Nice, @malcev thank you. Below is working code for @AHK_user's page using your code above. No doubt has bugs, redundancies and other overkill but works.
I can never find @teadrinker's Chrome.ahk when I search the forum so it's attached as well for those who may find it useful. I use it as 'tdChrome.ahk in this script.

Code: Select all

#Include tdChrome.ahk
SetTitleMatchMode, 2
;FileCreateDir, ChromeProfile


ChromeInst := new Chrome("ChromeProfile")
Sleep, 3000
PageInstance := ChromeInst.GetPage()
PageInstance.Call("Page.navigate", {"url": "https://the-internet.herokuapp.com/javascript_alerts"})
PageInstance.WaitForLoad()
sleep, 3000


global PageInst
PageInst := ChromeInst.GetPage(,,"callback")
PageInst.Call("Page.enable")

PageInstance.Evaluate("document.querySelector(""button[onclick='jsAlert()']"").click();")


; ┌─────────────────────────┐
; │  Close Browser routine  │
; └─────────────────────────┘

msgbox, ,Exiting, Exiting script, 2
PageInstance.Call("Browser.close")


PageInstance.Disconnect()
PageInstance := ""
ChromeInst := ""
ChromeInstance.Kill()
WinKill, chrome.exe

; Kill conhost.exe so it doesn't hang around.
; 
DetectHiddenWindows, On
; From GeekDude's tips and tricks: https://www.autohotkey.com/boards/viewtopic.php?f=7&t=7190
Run, cmd,, Hide, PID
WinWait, ahk_pid %PID%
DllCall("AttachConsole", "UInt", PID)

; Run another process that would normally
; make a command prompt pop up, such as
; RunWait, cmd /c dir > PingOutput.txt
Runwait, taskkill /im conhost.exe /f 
; Thanks to @flyingDman post from 2010, 
; https://autohotkey.com/board/topic/49732-kill-process/

; Close the hidden command prompt process
Process, Close, %PID%
ExitApp

callback(event)																				
{
   if (event.method = "Page.javascriptDialogOpening") {
      sleep, 3000
      PageInst.Call("Page.handleJavaScriptDialog", {"accept": LightJson.true}, false)
   }
}


/* new malcev code
global PageInst
PageInst := ChromeInst.GetPage(,,"callback")
PageInst.Call("Page.enable")
return

callback(event)																				
{
   if (event.method = "Page.javascriptDialogOpening")
      PageInst.Call("Page.handleJavaScriptDialog", {"accept": LightJson.true}, false)
}

*/
Regards,
burque505
Thanks a lot for the perfect example, It works well and I learned a lot from these conversations. :dance:

The reference to https://www.autohotkey.com/boards/viewtopic.php?f=7&t=7190 is also quite interesting.

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 25 Mar 2021, 11:41

@AHK_user, :thumbup: .
Here's a version (probably has bugs but works) that automates all three popups.
Spoiler

jsong55
Posts: 42
Joined: 30 Mar 2021, 22:02

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by jsong55 » 02 Apr 2021, 23:55

I managed to get the url of the image, not sure how to save it

Code: Select all

new Chrome()
; page := Chrome.GetPage() ; initialize if chrome is already open and logged in
; Page.WaitForLoad()  
page.Call("Page.navigate", {"url" : "https://en.wikipedia.org/wiki/AutoHotkey"})  
Page.WaitForLoad()  
ImageFile := page.Evaluate("document.getElementsByClassName('image')[0].href").Value
Msgbox, % ImageFile
Can someone advise please

AHK_user
Posts: 102
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by AHK_user » 03 Apr 2021, 05:28

jsong55 wrote:
02 Apr 2021, 23:55
I managed to get the url of the image, not sure how to save it

Code: Select all

new Chrome()
; page := Chrome.GetPage() ; initialize if chrome is already open and logged in
; Page.WaitForLoad()  
page.Call("Page.navigate", {"url" : "https://en.wikipedia.org/wiki/AutoHotkey"})  
Page.WaitForLoad()  
ImageFile := page.Evaluate("document.getElementsByClassName('image')[0].href").Value
Msgbox, % ImageFile
Can someone advise please
The command UrlDownloadToFile is what you want:
https://www.autohotkey.com/docs/commands/URLDownloadToFile.htm

jsong55
Posts: 42
Joined: 30 Mar 2021, 22:02

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by jsong55 » 03 Apr 2021, 07:17

@AHK_user
Thank you! That works well. Actually I found another method that is also good. Would love to contribute here. Try my code below.

Code: Select all

; Change the path of the include file where you store tdChrome.ahk or Chrome.ahk
#Include pathto\tdChrome.ahk

ClassName := "profile-background-image__image relative full-width full-height"
ConsoleJS =										            ; code that works in Chrome console, remember to replace 'ClassNameGoesHere'
(
    try {document.getElementsByClassName('ClassNameGoesHere')[0].src;}
catch (error) {value : 0;}
)
js := StrReplace(ConsoleJS,"ClassNameGoesHere",ClassName)	; js that we are going to pass into Evaluate function

urlObj := ["https www.linkedin.com /in/kim-kardashian-642064209/","https://www.linkedin.com/in/vanessahudgens/","https://www.linkedin.com/in/barackobama/"]  Broken Link for safety ; stores url in an array

page := Chrome.GetPage()                                    ; instantiate class and act on current page
guivariable := 1                                            ; to assign a unique veriable to each picture in the gui
Loop, % urlObj.MaxIndex() {
    page.Call("Page.navigate", {"url" : urlObj[A_Index]})   ; visits the page
    Page.WaitForLoad()                                      ; wait for page to load
    
    Gui, -MinimizeBox +Resize
    While (Page.Evaluate(js).Value = 0) {                   ; Value will be integer 0 if the Element is NOT FOUND
        Sleep, 500                                          ; we will sleep and try again for up to 10 times. If your connection is slow, increase the next line from 10 to 30
            If A_Index > 10
                break
    }
    If (Page.Evaluate(js).Value <> 0) {                     ; If value not 0, means the Element IS FOUND, now we can proceed
        image_url := Page.Evaluate(js).Value
        guivariable++
        Gui, Add, ActiveX, xm y+section w782 h195.5 vWB%guivariable%, % "about:" HTML_Page
        WebPic(WB%guivariable%, image_url, "w782 h195.5 cFFFFFF")
        Gui, Show, Autosize, Image from site
    }
    
}

; thanks to someone who posted this on forum
WebPic(WB, Website, Options := "") {
	RegExMatch(Options, "i)w\K\d+", W), (W = "") ? W := 50 :
	RegExMatch(Options, "i)h\K\d+", H), (H = "") ? H := 50 :
	RegExMatch(Options, "i)c\K\d+", C), (C = "") ? C := "EEEEEE" :
	WB.Silent := True
	HTML_Page :=
	(RTRIM
	"<!DOCTYPE html>
		<html>
			<head>
				<style>
					body {
						background-color: #" C ";
					}
					img {
						top: 0px;
						left: 0px;
					}
				</style>
			</head>
			<body>
				<img src=""" Website """ alt=""Picture"" style=""width:" W "px;height:" H "px;"" />
			</body>
		</html>"
	)
	While (WB.Busy)
		Sleep 10
			
	WB.Navigate("about:" HTML_Page)
	WB.document.body.style.setAttribute("margin", 0) ; remove borders (maybe)
	Return HTML_Page
}

fenchai
Posts: 245
Joined: 28 Mar 2016, 07:57

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by fenchai » 07 Apr 2021, 12:09

Anybody knows how to insert text into this search bar?

https://www.js-filter.com/catalogue

I have tried doing

Code: Select all

wp.Evaluate("document.querySelector('#txtPartNo').value = 'hello'")
but it doenst work.

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 07 Apr 2021, 12:28

@fenchai, I see there's a "helper-label" that may need to be cleared first. Untested with Chrome.ahk but works in the DevTools console:

Code: Select all

document.querySelector("div[id='product-search'] label:nth-child(2)").innerText = "";
I think in your script it might have to be this

Code: Select all

wp.Evaluate("document.querySelector(""div[id='product-search'] label:nth-child(2)"").innerText = '';")
but it generally takes me several tries to get the quoting right.
After that I think you could execute your code as above.
Regards,
burque505

Tre4shunter
Posts: 82
Joined: 26 Jan 2016, 16:05

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by Tre4shunter » 07 Apr 2021, 13:24

@fenchai

I'd do something like this to Enter, and then submit that form:

Code: Select all

document.querySelector('#frmPartNoSearch .input-field').className = 'input-field is-charged';
document.querySelector('#txtPartNo').value = 'test value';
document.querySelector('#frmPartNoSearch ').submit();
the reason i change the classname initially is due to how they have that input setup to be all fancified. you don't really need to do that.
but if you want to see it change the input nicely just run the first two lines.

Code: Select all

js_to_eval = 
(
document.querySelector('#frmPartNoSearch .input-field').className = 'input-field is-charged';
document.querySelector('#txtPartNo').value = 'test value';
)
wp.Evaluate(js_to_eval)

fenchai
Posts: 245
Joined: 28 Mar 2016, 07:57

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by fenchai » 07 Apr 2021, 19:52

@Tre4shunter

Thanks for the useful tips and solution, it works perfectly and I learned something new again.
Is there a guide to learn more about the querySelector method? or do I need to learn HTML and css in order to understand more?

Tre4shunter
Posts: 82
Joined: 26 Jan 2016, 16:05

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by Tre4shunter » 08 Apr 2021, 13:18

Hey @fenchai

No real 'magic' solution to understanding it better besides using it more and more.

This is a good reference:
https://www.w3schools.com/cssref/css_selectors.asp

I probably have it open anytime im using css, lol. Glad i could help.

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 08 Apr 2021, 13:48

Hi @fenchai, @Tre4shunter is really good at this.
I always have to refresh my memory on CSS selectors with Flukeout, which is actually fun.

Tre4shunter
Posts: 82
Joined: 26 Jan 2016, 16:05

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by Tre4shunter » 08 Apr 2021, 14:45

@burque505 -

Thats a really cool website! I like that, thanks!

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

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by burque505 » 15 Apr 2021, 13:55

User @Nussbeisser in the German-language forum shared :arrow: here that a Chrome update to v90 trashes scripts. I did for me too. The following fixed it for me, be interested to know others' experiences.
1) Run scripts as admin. UPDATE: @Nussbeisser reports this isn't needed if step 2 is performed.
Spoiler
2) Provide an absolute path to your ChromeProfile folder, even if it's in the same directory as your script.

Code: Select all

;FileCreateDir, ChromeProfile ; run script at least once with this uncommented.
ChromeInst := new Chrome("C:\Users\SomeRandomUser\Desktop\AHK\Chrome.ahk\Chrome.ahk-1.2\ChromeProfile")
I also set Chrome.exe to run as admin, but that's probably overkill. UPDATE: It was indeed overkill.
Regards,
burque505

evilmanimani
Posts: 13
Joined: 24 Jun 2020, 16:42

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by evilmanimani » 02 May 2021, 15:44

This took a while to figure out, but I thought I'd share since it's related. So I was trying to attempt to automatically submit a basic authentication alert if there were already values filled, however it's not something that's normally visible with window spy, so usually in those cases I turn to Acc.ahk, however a weird quirk I noticed is that if you don't wait till the alert is fully up, and change focus away from Chrome before you try to check it, acc_get won't return anything, so that said, this should help auto-submit those dialogs:

Code: Select all

vWin := "ahk_exe chrome.exe"
WinActivate, % vWin
WinWaitActive, % vWin, , 1
Sleep 500
WinActivate, ahk_class Shell_TrayWnd    ; Change focus to the start bar
If (Acc_Get("Value", "4.2.1.2.1.3",0, vWin )    ; Check for filled username field
&& Acc_Get("Value", "4.2.1.2.1.5",0, vWin))    ; Password field
	Acc_Get("Object","4.2.1.2.2.1",0, vWin).accDoDefaultAction(0)    ; Hit "Sign in"

hisrRB57
Posts: 13
Joined: 13 Jan 2019, 11:43

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by hisrRB57 » 07 May 2021, 05:21

Hi, I am using teadrinkers tdChrome.ahk and I wonder when an exception occurs the timer started in the event method should be deleted or not?

here :

Code: Select all

		Call(DomainAndMethod, Params:="", WaitForResponse:=True)
		{
			if !this.Connected
				throw Exception("Not connected to tab")

and here :

Code: Select all

		Evaluate(JS)
		{
			response := this.Call("Runtime.evaluate",
			( LTrim Join
			{
				"expression": JS,
				"objectGroup": "console",
				"includeCommandLineAPI": LightJson.true,
				"silent": LightJson.false,
				"returnByValue": LightJson.false,
				"userGesture": LightJson.true,
				"awaitPromise": LightJson.false
			}
			))
			
			if (response.exceptionDetails)
				throw Exception(response.result.description,, LightJson.Stringify(response.exceptionDetails))
			
			return response.result
		}

Timer set code:

Code: Select all

		Event(EventName, Event)
		{
			; If it was called from the WebSocket adjust the class context
			if this.Parent
				this := this.Parent
			
			; TODO: Handle Error events
			if (EventName == "Open")
			{
				this.Connected := True
				BoundKeepAlive := this.BoundKeepAlive
				SetTimer, %BoundKeepAlive%, 15000
After I have processed a lot page.evaluates it seems a page.disconnect / timer delete is missed and the background timers keep throwing exceptions

Anyone a suggestion?

jsong55
Posts: 42
Joined: 30 Mar 2021, 22:02

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by jsong55 » 09 May 2021, 21:15

Edit I found a fullproof fix from few suggestions above

Run this code first -

Code: Select all

Value = "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 -- "`%1"
RegWrite, REG_SZ, HKEY_CLASSES_ROOT, ChromeHTML\shell\open\command, , %Value%
Run "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
Then we are good to go!! :)

Question now is .. How to create a IF statement to detect if Chrome Instance is in Debug mode?

Original Problem Statement
Need some help, Chrome.ahk suddenly stopped working for me.

I was doing fine for a few weeks then suddenly it can't seem to the debug mode.

This is the error I got

Error in #Include file Chrome.ahk
Description: A connection with the server could not be established.

I've already tried forcing chrome to run in debug through
1. Shortcut
2. Using this code

Code: Select all

Run "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222

inseption86
Posts: 129
Joined: 19 Apr 2018, 00:24

Re: [Library] Chrome.ahk - Automate Google Chrome using native AutoHotkey. No Selenium!

Post by inseption86 » 10 May 2021, 00:59

How do I start a new chrome process? if one is already running "... chrome.exe --remote-debugging-port = 9222". My url is launched not in the new chrome, but already in the previously launched one

Code: Select all

URL := "
    
profile := A_Temp "\ChromeProfile"
if !FileExist(profile)
	FileCreateDir, % profile 

ChromeInst := new Chrome(profile,, "--incognito") ; ,, "--headless") 
Page := ChromeInst.GetPage()
Page.Call("Page.navigate", {"url": URL}) 
Page.WaitForLoad()

Post Reply

Return to “Scripts and Functions”