Get the URL of the current (active) browser tab

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Get the URL of the current (active) browser tab

08 Jun 2014, 13:19

Hello everyone.

Short version: The code below finds out the URL of the current (active) browser tab for most of the modern browsers.

Long version:
How to get the URL of the browser tab I'm using? The problem is quite common and there have been scripts to tackle it here and in the old forum.

The best solution for quite sometime (IMHO) was Sean's DDE code but unfortunately Google Chrome doesn't support DDE. Recent changes to Chrome invalidated the Chrome_OmniboxView workaround so I didn't knew how to get it until I saw uname's use of the ACC library (Sean strikes again :D). uname's code depended on the language used in Windows (I use Win7 x64 in Spanish) but I found out a workaround. I even managed to extend my solution to cover most of the Chromium-based browsers (all but Vivaldi), and even got it to work in Maxthon.

Anyway, the code below finds out the URL of the current (active) browser tab. I've tested successfully (on Win7 x64 Spanish) with the following browsers:
  • Google Chrome
  • Mozilla Firefox
  • Internet Explorer 11
  • Opera
  • Microsoft Edge
  • Opera 12
  • Maxthon
  • Iron
  • Coowon
  • Slimjet
  • Vivaldi (if run with the --force-renderer-accessibility switch)
I'd appreciate any feedback, particularly if it DOESN'T work :P

Code: Select all

; AutoHotkey Version: AutoHotkey 1.1
; Language:           English
; Platform:           Win7 SP1 / Win8.1 / Win10
; Author:             Antonio Bueno <user atnbueno of Google's popular e-mail service>
; Short description:  Gets the URL of the current (active) browser tab for most modern browsers
; Last Mod:           2016-05-19

Menu, Tray, Icon, % A_WinDir "\system32\netshell.dll", 86 ; Shows a world icon in the system tray

ModernBrowsers := "ApplicationFrameWindow,Chrome_WidgetWin_0,Chrome_WidgetWin_1,Maxthon3Cls_MainFrm,MozillaWindowClass,Slimjet_WidgetWin_1"
LegacyBrowsers := "IEFrame,OperaWindowClass"

^+!u::
	nTime := A_TickCount
	sURL := GetActiveBrowserURL()
	WinGetClass, sClass, A
	If (sURL != "")
		MsgBox, % "The URL is """ sURL """`nEllapsed time: " (A_TickCount - nTime) " ms (" sClass ")"
	Else If sClass In % ModernBrowsers "," LegacyBrowsers
		MsgBox, % "The URL couldn't be determined (" sClass ")"
	Else
		MsgBox, % "Not a browser or browser not supported (" sClass ")"
Return

GetActiveBrowserURL() {
	global ModernBrowsers, LegacyBrowsers
	WinGetClass, sClass, A
	If sClass In % ModernBrowsers
		Return GetBrowserURL_ACC(sClass)
	Else If sClass In % LegacyBrowsers
		Return GetBrowserURL_DDE(sClass) ; empty string if DDE not supported (or not a browser)
	Else
		Return ""
}

; "GetBrowserURL_DDE" adapted from DDE code by Sean, (AHK_L version by maraskan_user)
; Found at http://autohotkey.com/board/topic/17633-/?p=434518

GetBrowserURL_DDE(sClass) {
	WinGet, sServer, ProcessName, % "ahk_class " sClass
	StringTrimRight, sServer, sServer, 4
	iCodePage := A_IsUnicode ? 0x04B0 : 0x03EC ; 0x04B0 = CP_WINUNICODE, 0x03EC = CP_WINANSI
	DllCall("DdeInitialize", "UPtrP", idInst, "Uint", 0, "Uint", 0, "Uint", 0)
	hServer := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", sServer, "int", iCodePage)
	hTopic := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "WWW_GetWindowInfo", "int", iCodePage)
	hItem := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "0xFFFFFFFF", "int", iCodePage)
	hConv := DllCall("DdeConnect", "UPtr", idInst, "UPtr", hServer, "UPtr", hTopic, "Uint", 0)
	hData := DllCall("DdeClientTransaction", "Uint", 0, "Uint", 0, "UPtr", hConv, "UPtr", hItem, "UInt", 1, "Uint", 0x20B0, "Uint", 10000, "UPtrP", nResult) ; 0x20B0 = XTYP_REQUEST, 10000 = 10s timeout
	sData := DllCall("DdeAccessData", "Uint", hData, "Uint", 0, "Str")
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hServer)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hTopic)
	DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hItem)
	DllCall("DdeUnaccessData", "UPtr", hData)
	DllCall("DdeFreeDataHandle", "UPtr", hData)
	DllCall("DdeDisconnect", "UPtr", hConv)
	DllCall("DdeUninitialize", "UPtr", idInst)
	csvWindowInfo := StrGet(&sData, "CP0")
	StringSplit, sWindowInfo, csvWindowInfo, `" ;"; comment to avoid a syntax highlighting issue in autohotkey.com/boards
	Return sWindowInfo2
}

GetBrowserURL_ACC(sClass) {
	global nWindow, accAddressBar
	If (nWindow != WinExist("ahk_class " sClass)) ; reuses accAddressBar if it's the same window
	{
		nWindow := WinExist("ahk_class " sClass)
		accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindow))
	}
	Try sURL := accAddressBar.accValue(0)
	If (sURL == "") {
		WinGet, nWindows, List, % "ahk_class " sClass ; In case of a nested browser window as in the old CoolNovo (TO DO: check if still needed)
		If (nWindows > 1) {
			accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindows2))
			Try sURL := accAddressBar.accValue(0)
		}
	}
	If ((sURL != "") and (SubStr(sURL, 1, 4) != "http")) ; Modern browsers omit "http://"
		sURL := "http://" sURL
	If (sURL == "")
		nWindow := -1 ; Don't remember the window if there is no URL
	Return sURL
}

; "GetAddressBar" based in code by uname
; Found at http://autohotkey.com/board/topic/103178-/?p=637687

GetAddressBar(accObj) {
	Try If ((accObj.accRole(0) == 42) and IsURL(accObj.accValue(0)))
		Return accObj
	Try If ((accObj.accRole(0) == 42) and IsURL("http://" accObj.accValue(0))) ; Modern browsers omit "http://"
		Return accObj
	For nChild, accChild in Acc_Children(accObj)
		If IsObject(accAddressBar := GetAddressBar(accChild))
			Return accAddressBar
}

IsURL(sURL) {
	Return RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^:/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
}

; The code below is part of the Acc.ahk Standard Library by Sean (updated by jethrow)
; Found at http://autohotkey.com/board/topic/77303-/?p=491516

Acc_Init()
{
	static h
	If Not h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromWindow(hWnd, idObject = 0)
{
	Acc_Init()
	If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return ComObjEnwrap(9,pacc,1)
}
Acc_Query(Acc) {
	Try Return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Children(Acc) {
	If ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	Else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		If DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			Return Children.MaxIndex()?Children:
		} Else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
}
EDIT 2014-06-17:
- Faster in Chromium browsers: After the first use, successive queries are instantaneous (faster than DDE!) Thanks to XeroByte for the nudge ;-)
- Improved error messages in the hotkey example
- Tested without problems in all AutoHotkey versions (U32, A32, U64) and also in Windows 8.1

EDIT 2015-10-18:
- Now it works with Microsoft Edge (only tested via VM) and Slimjet (both suggestions by Kudos)
- Better URL detection (thanks LarryC for the feedback)
- Added workaround for runtime errors suggested by Kipp a year ago
- Removed support for Google's failed Origin Chip experiment

EDIT 2016-05-15:
- Better support for Microsoft Edge
- DDE is now used only for legacy browsers (specifically, Internet Explorer and Opera 12)
- Identified two browsers where the script doesn't work (it can't reach the address bar): Pale Moon and Vivaldi :think:

EDIT 2016-05-19:
- Better detection of the address bar
- Vivaldi now supported as long as is run with the --force-renderer-accessibility switch on (and optional, but recommended, check the option "Address Bar/Show Full URL")
- Pale Moon won't be supported as they explicitly disabled the accessibility features: https://www.palemoon.org/technical.shtml#features (thanks qwerty12 for the info)


Regards from Spain,
Antonio
Last edited by atnbueno on 19 May 2016, 15:49, edited 9 times in total.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Get the URL of the current (active) browser tab

09 Jun 2014, 11:56

Wonderful! The script works with AutoHotkeyA32 too.
LarryC
Posts: 28
Joined: 30 Sep 2013, 12:14

Re: Get the URL of the current (active) browser tab

15 Jun 2014, 19:34

Hey, anybody noticed, this script stopped working on Chrome 35??
It works of FireFox.
It worked well last few days with Chrome 35, but today, no dice??
LarryC
Posts: 28
Joined: 30 Sep 2013, 12:14

Re: Get the URL of the current (active) browser tab

16 Jun 2014, 14:03

Hmm, sorry, now its working again. No explanation.
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Re: Get the URL of the current (active) browser tab

17 Jun 2014, 16:02

Hello again.

Slightly improved version in the OP:
- Faster in Chromium browsers: After the first use, successive queries are instantaneous (faster than DDE!) Thanks to XeroByte (in the old forum) for the nudge ;-)
- Improved error messages in the hotkey example
- Tested without problems in all AutoHotkey versions (U32, A32, U64) and also in Windows 8.1


Regards,
Antonio
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Re: Get the URL of the current (active) browser tab

18 Oct 2015, 17:41

Hello again.

It's been more than a year (!), so it's time for an updated version in the OP:
- Now it works with Microsoft Edge (only tested via VM) and Slimjet (both suggestions by Kudos)
- Better URL detection (thanks LarryC for the feedback)
- Added workaround for runtime errors suggested by Kipp (in the old forum) a year ago
- Removed support for Google's failed Origin Chip experiment


Regards from Spain,
Antonio
ahk7
Posts: 572
Joined: 06 Nov 2013, 16:35

Re: Get the URL of the current (active) browser tab

19 Oct 2015, 11:26

Thanks for the update, seems to work well.

There are two non-mainstream browsers where it doesn't work (yet): Note: I'm posting this on autohotkey.com/boards/ (the phbbb3 forum) to see if it works OK
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Get the URL of the current (active) browser tab

19 Oct 2015, 16:52

Vivaldi, with Atle Mo! He maintains Subtle patterns! :D
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
SlowPoster[1H+]

Re: Get the URL of the current (active) browser tab

25 Nov 2015, 05:21

Ola. Nice handy script you got there, been using Internet Explorer URL-detection for a while but
since we recently moved up a notch with Edge I had to drop IE as my 2nd/3rd browser. Can't bare it's slowness anymore, lol
Sadly...

:terms: Here URL-detection fails with Microsoft Edge 20.10240.16384.0 - ApplicationFrameWindow class
Tried several tweaks to no avail... Got any ideas? I'm on Windows 10 x64, AHK v1.1.22.09 Unicode 32-bit

By the way, here are some ideas for (fast and secure) browsers to extend support with (or to use):
Comodo Dragon (Chromium-based)
Comodo IceDragon (Mozilla-based)
Comodo Chromodo (Chromium-based - newest addition) :thumbup:
User avatar
JoeSchmoe
Posts: 129
Joined: 08 Dec 2014, 08:58

Re: Get the URL of the current (active) browser tab

27 Nov 2015, 11:28

Thanks so much for writing this. Just knowing I have a library that will work with all of the big browsers is incredibly helpful.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Get the URL of the current (active) browser tab

28 Nov 2015, 01:50

@atnbueno, Thank You! I had to rename your function IsUrl() once more to IsUrlString() cause I have another function IsUrl() (see below), which checks not only the form of a url, but also the content, the real existence of the target.

Code: Select all

IsUrl(Url) {
   ComObjError(false) ; Verhindert einen ERROR, wenn die Url nicht existiert
   WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   WebRequest.Open("GET", Url)
   WebRequest.Send()
   Zwi := WebRequest.ResponseText
   If StrLen(Zwi)=0 ; Wenn nichts geladen werden konnte.
      Return false
   Return true
}
Your new RegEx-Formula

Code: Select all

RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^:/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
in your (new) function IsUrl() (Line 90) is faulty. It does not accept the url

Code: Select all

http://anonymouse.org/cgi-bin/anon-www_de.cgi/http://www.mittelbayerische.de
as a url. Your former RegEx-Formula

Code: Select all

RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?:(?<Username>[^:]+)(?::(?<Password>[^@]+))?@)?(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
works fine.
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Re: Get the URL of the current (active) browser tab

29 Nov 2015, 17:41

@ahk7: Thanks for the links. I'll update the script soon with a fix for Firefox x64 (and Waterfox). For Vivaldi is too soon (is doesn't appear to support neither the old DDE nor the MSAA API).

@SlowPoster: I only have Windows 10 in a virtual machine right now, but in it my script works fine with Edge if you add "ApplicationFrameWindow" to the If sClass In line in GetActiveBrowserURL().

@Johnny R: You're right, but there's no need to go back to the old RegEx. This one should do the work:

Code: Select all

RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
As mentioned before I have a new version of the script with significant changes. I'll publish it once I've polished and tested it properly (hopefully soon).


Regards,
Antonio
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Get the URL of the current (active) browser tab

30 Nov 2015, 09:08

@Antonio, the new regex-formula works fine now. Thank You!
SlowPoster[1H+]

Re: Get the URL of the current (active) browser tab

30 Nov 2015, 21:17

Script works fine :bravo: Maybe I was too sleepy to fiddle around with it last time... lol
Now I can finally start to manage my browsing madness again :dance: Thanks !
rg_software
Posts: 2
Joined: 19 Dec 2015, 09:24

Re: Get the URL of the current (active) browser tab

19 Dec 2015, 09:26

Sorry for trouble, but... how to use this script properly? :)
If I just run GetActiveBrowserURL.ahk, it says "error at line 64 -- this line does not contain a recognized action".
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Re: Get the URL of the current (active) browser tab

20 Dec 2015, 03:44

@rg_software, I don't know what to tell you :eh: That shouldn't happen :wtf:

:think: What version of AutoHotkey are you using?
rg_software
Posts: 2
Joined: 19 Dec 2015, 09:24

Re: Get the URL of the current (active) browser tab

21 Dec 2015, 07:17

atnbueno wrote: :think: What version of AutoHotkey are you using?
Oh my, sorry for this false alarm! It looks like my installation was really outdated, now everything works fine :)
mc-lemons
Posts: 6
Joined: 19 Jan 2016, 18:22

Re: Get the URL of the current (active) browser tab

19 Jan 2016, 18:31

Need some help here as I am not much of a coder. I have downloaded GetActiveBrowserURL.ahk, brought it into my script with #Include, but can't figure out how to get it to work the way I want to.

I basically want it to work the same way as #IfWinActive, but instead "If URL Active". That way, a set hotkeys can be set to do one thing when on a certain webpage, and something different when another webpage is active.
User avatar
atnbueno
Posts: 89
Joined: 12 Oct 2013, 04:45
Contact:

Re: Get the URL of the current (active) browser tab

27 Jan 2016, 10:25

Hello mc-lemons.

Would something like this serve you? (untested code)

Code: Select all

#a::
sURL := GetActiveBrowserURL()
IfInString, sURL, autohotkey.com
	MsgBox, Welcome!
Else
	MsgBox, 4, , Do you want to go to autohotkey.com? ; 4=Yes/no
Return
Doing it like #IfWinActive would require something to check the URL of any browser either continuously or everytime each particular address bar content changes. I actually have such code, but it's quite complex. I think the code above may be functionally equivalent in your case, and it's significantly easier to understand, reuse and adapt.


Regards,
Antonio
mc-lemons
Posts: 6
Joined: 19 Jan 2016, 18:22

Re: Get the URL of the current (active) browser tab

07 Feb 2016, 14:43

Antonio,

I appreciate the response. Your code worked (the code I tried on my own was very close, but had one small difference that was causing it to not work). I would also be interested in your code that acts just like #IfWinActive. I could just save it as a separate script and use #Include to bring it into my scripts, correct?

Thanks again,
Michael

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 74 guests