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

Post your working scripts, libraries and tools for AHK v1.1 and older
bmilcs
Posts: 11
Joined: 27 Feb 2017, 13:54

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

25 Jun 2018, 10:47

Deleted.
Last edited by bmilcs on 31 May 2019, 16:57, edited 1 time in total.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

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

25 Jun 2018, 11:06

Manuf
Manuf wrote:Hi sirs. Can you help me with this simple task

i want to write a script to detect
- can check if webpage full loaded
- can check if webpage loaded error
- can check if an element display after an action. Ie: after upload a file, a button will turn from gray to yellow. i want to check that state of the button.

Thanks you
I'm sorry but I can't help with this without a much more thorough understanding of your situation and your goals. I don't have the time to dive that deeply into it right now.

You should be able to check the page readiness state by running PageInst.Evaluate("document.readyState"), which should return how loaded the page is. For the rest of your post I'm not sure.


bmilcs
bmilcs wrote:I have a few questions for you regarding this script:

#1) PageInst.Call("Page.navigate", {"url": address})

I am trying to pass text that isn't a specific URL, but text that I would normally type to search google for. However, I'm receiving errors from Chrome.AHK. Is there a section of the Chrome.ahk script I can edit to allow for non-url text to be passed as valid?
I don't think you can do that directly, but a viable alternative may be to generate a google search url and navigate to that. For example,

Code: Select all

PageInst.Call("Page.navigate", {"url": "https://google.com/search?q=" UriEncode("Search Terms")})

; Modified by GeekDude from http://goo.gl/0a0iJq
UriEncode(Uri, RE="[0-9A-Za-z]") {
	VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0), StrPut(Uri, &Var, "UTF-8")
	While Code := NumGet(Var, A_Index - 1, "UChar")
		Res .= (Chr:=Chr(Code)) ~= RE ? Chr : Format("%{:02X}", Code)
	Return, Res
}

bmilcs wrote:#2) How do I retrieve the current URL of the active PageInst?
Try PageInst.Evaluate("window.location.href")

bmilcs wrote:#3) I am a dummy, but are there commands that work with Chrome.ahk that aren't mentioned as examples?
I have zero experience with this, and am wondering if there is another resource detailing the COMS available to us via Chrome.ahk?
In other words, does this just unlock the ability to use Chrome and not give you a full scope of possibilities?
As mentioned at the top of the original post, the Chrome DevTools Protocol's documentation lists a lot of endpoints that you can use from PageInst.Call: https://chromedevtools.github.io/devtools-protocol/

bmilcs wrote:I'm dying to learn more but feel like I'm missing something. Thanks!

Edit: Apologies if I misused vocab or sound like a moron. I've been able to successfully scrape metadata off of websites which is quite exciting! Thank you again for posting such a tremendously useful script!
No need to apologize. I love when people are eager to learn :) . Good luck with your code!
bmilcs
Posts: 11
Joined: 27 Feb 2017, 13:54

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

01 Jul 2018, 17:58

Deleted.
Last edited by bmilcs on 31 May 2019, 17:23, edited 1 time in total.
bmilcs
Posts: 11
Joined: 27 Feb 2017, 13:54

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

02 Jul 2018, 14:15

Deleted.
Last edited by bmilcs on 31 May 2019, 17:23, edited 1 time in total.
bmilcs
Posts: 11
Joined: 27 Feb 2017, 13:54

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

02 Jul 2018, 18:14

And as I wear out my welcome here, I think I've found a bug of some type. After I make a dozen or so DOM JS calls, AHK locks up and this is what I'm seeing for output:

Code: Select all

037: if i := InStr("{[", ch)  
047: if InStr("}]", ch)  
049: ObjRemoveAt(stack, 1)  
050: next := stack[1]==tree ? "" : is_arr[stack[1]] ? ",]" : ",}"
051: }
134: }
010: While,( (ch := SubStr(src, ++pos, 1)) != "" )
136: Return,tree[1]
---- E:\autohotkey\Infraware\Chrome\Chrome.ahk
316: fnCallback := this.fnCallback
317: if (newData := %fnCallback%(data))  
320: if this.responses.HasKey(data.ID)  
322: }
329: } (0.91)
Those are the last lines every single time it locks up. I've tried running the same getelementby syntax, which I know works for a fact, several times and it locks up at the same point every time.

;-----------------------------------------------------------------------------------------------------------------------------

EDIT: SOLVED.

Code: Select all

PageInst.Disconnect()
After hours of tinkering with the code and browsing the Chrome DevTools page, I stumbled upon Page.Disconnect(). Apparently, the connection with Chrome was hitting the max allotment of time or only allows for X amount of actions per connection.

I added this to the end of the cycle of actions that I perform. This has completely fixed all issues I was having in regards to AHK freezing up after X amount of lines or time passed.

Hopefully this helps someone <3

The syntax
Manuf

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

09 Jul 2018, 04:23

To @Geekdude

Thanks for your answer. May you help me with this code?

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#Include C:\Program Files\AutoHotkey\Chrome.ahk

ChromeInst := new Chrome()
PageInst := ChromeInst.GetPage()
PageInst.Call("Page.navigate", {"url": "http://google.com"})
PageInst.WaitForLoad()

sleep 10000

PageInst.Evaluate("setInterval(function(){var div = document.getElementsByName('btnK')[0];var rect = div.getBoundingClientRect();x = rect.left;alert("("x")");});")
x = PageInst.Evaluate("rect.left")
msgbox, %x%
I want to get the x coordinate value of a button but after i run the javascript function ( it works ), i cant assign it to a variable. How can i get the "x = react.left" value in autohotkey ?

Thanks you so much

p.s: Sorry if i cant say it clearly. If anyone know the answer, pls tell me. Thanks
KusochekDobra
Posts: 38
Joined: 25 Apr 2016, 18:00

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

21 Jul 2018, 18:33

Hello!
I tried to add to my code processing event "OnExit" and noticed, that the GUI is freeze after close a browser window. After that, I added messages on "OutputDebug" and it turned out that exit from program is unreachable. Could you check this effect on your system?

Code: Select all

#SingleInstance, Force
#NoEnv

OnExit, BeforeExit
#Include <Chrome>

; >>--++--<<  >>--++--<<
	ProfilePath  := "Chrome_Profile"
; >>--++--<<  >>--++--<<
	if (!FileExist(ProfilePath))
		FileCreateDir,% ProfilePath
; >>--++--<<  >>--++--<<


ChromeInst := new Chrome(ProfilePath,"about:blank","--no-first-run")
if !(PageInst := ChromeInst.GetPage())
{
	MsgBox, Could not retrieve page!
	ChromeInst.Kill()
	ExitApp
}
PageInst.Call("Page.navigate", {"url": "https://p.ahkscript.org/"})
PageInst.WaitForLoad()
MsgBox,,Title,Exit from app
	
ExitApp

BeforeExit:
	OutputDebug,Exit now
	try
		PageInst.Call("Browser.close") ; Fails when running headless
	catch
		ChromeInst.Kill()
		
	; |=> Next code is unreachable
	OutputDebug,Close Browser
	PageInst.Disconnect()
	OutputDebug,Disconnect
	ExitApp
KusochekDobra
Posts: 38
Joined: 25 Apr 2016, 18:00

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

22 Jul 2018, 05:45

Also noticed that adding a function call by event "Close" terminates the script earlier than the script itself describes. Sometimes the code finishes correctly, but more often it is incorrect:

Code: Select all

#SingleInstance, Force
#NoEnv

;OnExit, BeforeExit

#Include <Chrome>

; >>--++--<<  >>--++--<<
	ProfilePath  := "Chrome_Profile"
; >>--++--<<  >>--++--<<
	if (!FileExist(ProfilePath))
		FileCreateDir,% ProfilePath
; >>--++--<<  >>--++--<<
	pageSettings := {"ahkscript": {"funcName": "MsgFunc"}}
	page := new PageClass(ProfilePath, pageSettings)
; >>--++--<<  >>--++--<<


page.PageNavigate("https://p.ahkscript.org/")
MsgBox,,Title,Exit from app

;ExitApp
BeforeExit:
	page.Quit()
	ExitApp
	
MsgFunc(data) {
	if (data.method == "Console.messageAdded") {
		msg := data.params.message
		MsgBox,,Message from browser,% msg.text
	} else
		OutputDebug,% Format("data.method = {}", data.method)
}

Class PageClass
{
	__New(ProfilePath, pageSettings, URLs := "about:blank", ar := "") {
		this.tabs := {}, this.page := "", this.ProfilePath := ProfilePath
		this.pageSettings := pageSettings
		if (Chrome.FindInstances()) {
			this.ChromeInst := {"base": Chrome, "DebugPort": 9222}
		} else {
			this.ChromeInst := new Chrome(ProfilePath,URLs,Format("--no-first-run{}",ar ? (" " . ar) : ar))
		}
		this.GetTabs()
	}
	
	GetTabs() {
		pageIndex := 1, this_page := ""
		for i, obj in this.ChromeInst.GetPageList() {
			if ( obj.type == "page" ) {
				if ( !this.tabs.HasKey(page := this.GetDomainName(obj.url)) ) {
					bindFunc := this.pageSettings.HasKey(page)
					this.tabs[page] := { "pInst": New this.ChromeInst.Page(obj.webSocketDebuggerUrl
																			, bindFunc ? Func(this.pageSettings[page].funcName) : ""
																			, ObjBindMethod(this,"FreeConnection"))	; Delete this parameter for work
																			, "title": obj.title, "id": obj.id }
					(bindFunc && this.tabs[page].pInst.Call("Console.enable"))
					this.SetRootPage(page)
				} (pageIndex++ == 1 && this_page := page)
			}
		} this.page := this_page
	}
	
	FreeConnection() {
		this.GetTabs()
		if (!this.page) {
			ExitApp
		} for k, t in this.tabs {
			if (!t.pInst.Connected) {
				OutputDebug,% Format("Closed tab '{}'", k)
				this.tabs.Delete(k)
			}
		}
	}
	
	GetDomainName(d) {
		return RegExReplace(d, "https?://([w|p|info|forum]+\.)?([\w-]*)\..*", "$2")
	}
	
	PageNavigate(address, page := "") {
		this.page := page ? page : this.page
		this.tabs[this.page].pInst.WaitForLoad()
		this.tabs[this.page].pInst.Call("Page.navigate", {"url": address})
		this.tabs[this.page].pInst.WaitForLoad()
		if (this.page != this.GetDomainName(address)) {
			this.tabs[this.page].pInst.Disconnect()
			this.tabs.Delete(this.page)
			this.GetTabs()
		}
	}
	
	Quit(isDone := true, recycleProfile := false) {
		OutputDebug,Quit: Close the Browser
		if (isDone) {
			try
				this.tabs[this.page].pInst.Call("Browser.close")
			catch
				this.ChromeInst.Kill()
		}
		
		; |=> Next code is unreachable
		OutputDebug,Disconnect
		for k, t in this.tabs
			t.pInst.Disconnect()
		OutputDebug,Delete_Profile
		if (recycleProfile) {
			fPath := Format("{1}\{2}",A_ScriptDir,this.ProfilePath)
			FileRemoveDir,% fPath, 1
			i := 0
			while (i < 10, i++) {
				Sleep, 1000
				if (FileExist(fPath))
					FileRemoveDir,% fPath, 1
				else
					break
			}
		}
		OutputDebug,Finish
	}
}
Maybe I just do not apply my knowledge well. Could you help me with this, or would it be more efficient to track targetDestroyed, instead of adding a function?
Manuf

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

26 Jul 2018, 04:19

May i ask how to check if a webpage load error? i mean the web page loaded completely but error. I just want to know how to check if it happends. Thanks
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

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

28 Jul 2018, 22:24

GeekDude, there is a misprint in Chrome.ahk v1.2.
GeekDude wrote:

Code: Select all

		if (ChromePath == "")
			RegRead, ChromePath, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Pahs\chrome.exe
App Pahs — App Paths
KusochekDobra wrote:I tried to add to my code processing event "OnExit" ... it turned out that exit from program is unreachable.
I have the same issue on my Win 7 64 AHK 64.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

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

28 Jul 2018, 22:32

teadrinker

https://github.com/G33kDude/Chrome.ahk/ ... 2ef9258164

The fix has been applied and will be present in the next release.

Everyone else

I've seen your posts but haven't yet gotten to replying. I'll get there eventually, please be patient :thumbup:.
ocnuybear
Posts: 8
Joined: 15 Jul 2018, 12:52

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

30 Jul 2018, 04:44

Can Chrome.ahk be compiled into a stand alone DLL & called from 3rd party software?
Koiu

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

07 Aug 2018, 12:04

How to wait until all elements visible?

I try everything but i dont know how to make my script wait until all elements visible
- I try "PageInst.Evaluate("document.readyState")" to make sure the state page is " Complete" but the button still loading
- i try " PageInst.WaitForLoad()" and the button still loading

i really appreciate if anyone can help me. Thanks
mgroen
Posts: 97
Joined: 13 Jul 2018, 02:22

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

24 Aug 2018, 09:34

Hi, I'm new to automating Chrome with Autohotkey. If I run this script (see below), I get the error "Websocket.ahk cannot be opened"

Anybody able to assist me?

Code: Select all

#include Chrome.ahk

; Create an instance of the Chrome class using
; the folder ChromeProfile to store the user profile
FileCreateDir, ChromeProfile
ChromeInst := new Chrome("ChromeProfile")

; Connect to the newly opened tab and navigate to another website
; Note: If your first action is to navigate away, it may be just as
; effective to provide the target URL when instantiating the Chrome class
PageInst := ChromeInst.GetPage()
PageInst.Call("Page.navigate", {"url": "https://autohotkey.com/"})
PageInst.WaitForLoad()

; Execute some JavaScript
PageInst.Evaluate("alert('Hello World!');")

; Close the browser (note: this closes *all* pages/tabs)
PageInst.Call("Browser.close")
PageInst.Disconnect()

ExitApp
return
Attachments
2018-08-24_16-34-05.png
(79.1 KiB) Not downloaded yet
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

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

24 Aug 2018, 09:41

mgroen wrote:Hi, I'm new to automating Chrome with Autohotkey. If I run this script (see below), I get the error "Websocket.ahk cannot be opened"

Anybody able to assist me?
Make sure you're downloading the release file "Chrome.ahk_vX.Y.zip" from the releases page, not the source code. As you have noticed, GitHub does not include submodules (i.e. AutoHotkey-JSON and WebSocket.ahk) in its source downloads. The release has all the #Include's built in.

Image
(image from old release)
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

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

24 Aug 2018, 09:59

ocnuybear wrote:Can Chrome.ahk be compiled into a stand alone DLL & called from 3rd party software?
No, that's what Selenium is. There are other tutorials on this forum for using Selenium with AHK as the 3rd party software, but you can use it with any programming language.
Koiu wrote:How to wait until all elements visible?

I try everything but i dont know how to make my script wait until all elements visible
- I try "PageInst.Evaluate("document.readyState")" to make sure the state page is " Complete" but the button still loading
- i try " PageInst.WaitForLoad()" and the button still loading

i really appreciate if anyone can help me. Thanks
I'm not sure what the exact rules chrome uses are for showing the button in a loading state, but typically the approach you want to take in this situation is to wait for the elements you want to interact to have finished loading. Depending on how the page is built the way to do this can very a lot.
mgroen
Posts: 97
Joined: 13 Jul 2018, 02:22

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

24 Aug 2018, 10:37

is this framework also suitable for steering multiple Chrome sessions in parralell?
(for example: to simulate multiple users on a website).
euras
Posts: 429
Joined: 05 Nov 2015, 12:56

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

12 Sep 2018, 15:10

It may sound stupid, but I'm not a Chrome user and I dont have a clue how do I need to start Chrome in Debug mode? Can someone tell me or give a link where it's showed up?
w0z
Posts: 230
Joined: 19 Jun 2014, 08:21

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

12 Sep 2018, 19:03

euras wrote:It may sound stupid, but I'm not a Chrome user and I dont have a clue how do I need to start Chrome in Debug mode? Can someone tell me or give a link where it's showed up?
Hi, you can add --remote-debugging-port=9222 on a shortcut properties after "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" or wherever you chrome path is for you.

In this topic are more about how to configure Debug Mode.
https://autohotkey.com/boards/viewtopic ... 20#p181299
If I was helpful consider Donate me. :beer: , plz :D
Stavencross
Posts: 90
Joined: 24 May 2016, 16:42

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

21 Sep 2018, 09:00

bmilcs wrote:And as I wear out my welcome here, I think I've found a bug of some type. After I make a dozen or so DOM JS calls, AHK locks up and this is what I'm seeing for output:

Code: Select all

037: if i := InStr("{[", ch)  
047: if InStr("}]", ch)  
049: ObjRemoveAt(stack, 1)  
050: next := stack[1]==tree ? "" : is_arr[stack[1]] ? ",]" : ",}"
051: }
134: }
010: While,( (ch := SubStr(src, ++pos, 1)) != "" )
136: Return,tree[1]
---- E:\autohotkey\Infraware\Chrome\Chrome.ahk
316: fnCallback := this.fnCallback
317: if (newData := %fnCallback%(data))  
320: if this.responses.HasKey(data.ID)  
322: }
329: } (0.91)
Those are the last lines every single time it locks up. I've tried running the same getelementby syntax, which I know works for a fact, several times and it locks up at the same point every time.

;-----------------------------------------------------------------------------------------------------------------------------

EDIT: SOLVED.

Code: Select all

PageInst.Disconnect()
After hours of tinkering with the code and browsing the Chrome DevTools page, I stumbled upon Page.Disconnect(). Apparently, the connection with Chrome was hitting the max allotment of time or only allows for X amount of actions per connection.

I added this to the end of the cycle of actions that I perform. This has completely fixed all issues I was having in regards to AHK freezing up after X amount of lines or time passed.

Hopefully this helps someone <3

The syntax
I actually delt with this a while back and after talking to GeekDude about it, I realized, I was calling a new version of the class every time, so it would fail after about 5 versions of the class were created.

Instead, you should call the class once, connect to the page, and just redirect the page. Once you're done with the class, disconnect as you're talking about. This saves processing time since you're not regenerating the class over and over as well

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 129 guests