Get the URL of the current (active) browser tab

Post your working scripts, libraries and tools for AHK v1.1 and older
Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 30 Apr 2022, 00:19

@tdalon yes, this because by default Chrome doesn't display http(s) in it's address bar any more. This is also why @brunokitano's solution doesn't work for Chrome, because it works by looking for "http" (if in that code you change "if (oAcc.accValue(0) ~= "^http")" into "if (oAcc.accValue(0) ~= "^http|^\w+(\.\w+)+(\/|$)")" then it also starts working again). Http IS included if you activate the address bar first, for example by sending Ctrl+L:

Code: Select all

ControlSend, , ^l, A
Sleep, 100
MsgBox, % GetUrl("A")
Or you could check if the URL starts with "http(s)://" and conditionally add it to the front.

User avatar
tdalon
Posts: 41
Joined: 21 Apr 2017, 07:19
Location: Germany
Contact:

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

Post by tdalon » 01 May 2022, 07:56

@Descolada Thanks for the quick, competent help and explanation.
I would slightly modify the end of your function like this:

Code: Select all

GetUrl(wTitle:="A") {
; From Descolada https://www.autohotkey.com/boards/viewtopic.php?f=6&t=3702&e=1&view=unread#p459451
; does not require Acc Lib
	ErrorLevel := 0
	if !(wId := WinExist(wTitle)) {
		ErrorLevel := 1
		return
	}
	IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
	DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", wId, "ptr*", elementMain)   ; IUIAutomation::ElementFromHandle
	NumPut(addressbarStrPtr := DllCall("oleaut32\SysAllocString", "wstr", "Address and search bar", "ptr"),(VarSetCapacity(addressbar,8+2*A_PtrSize)+NumPut(8,addressbar,0,"short"))*0+&addressbar,8,"ptr")
	DllCall("oleaut32\SysFreeString", "ptr", addressbarStrPtr)
	if (A_PtrSize = 4) {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "int64", NumGet(addressbar, 0, "int64"), "int64", NumGet(addressbar, 8, "int64"), "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	} else {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "ptr", &addressbar, "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	}
	DllCall(NumGet(NumGet(elementMain+0)+5*A_PtrSize), "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", addressbarCondition, "ptr*", currentURLElement) ; IUIAutomationElement::FindFirst
	DllCall(NumGet(NumGet(currentURLElement+0)+10*A_PtrSize),"ptr",currentURLElement,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+&currentURL) ;IUIAutomationElement::GetCurrentPropertyValue
	ObjRelease(currentURLElement)
	ObjRelease(elementMain)
	ObjRelease(IUIAutomation)
    sUrl := StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
    If !sUrl { ;empty
        ErrorLevel := 1
        return
    }

    If !RegExMatch(sUrl,"^https?://")
        sUrl := "https://" . sUrl
	return sUrl
}

User avatar
tdalon
Posts: 41
Joined: 21 Apr 2017, 07:19
Location: Germany
Contact:

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

Post by tdalon » 02 May 2022, 00:33

@Descolada : Your approach seems faster than the Acc based recursive one. But it is totally cryptic to me. I would be curious to learn how you've come to it.

I am not 100% sure if the ErrorLevel variable should not be defined as global in the function. Else it wouldn't be returned to the calling script, right?

AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

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

Post by AHKStudent » 02 May 2022, 10:06

Descolada wrote:
29 Apr 2022, 03:06
Tested on Chrome and Edge, and no need to include Acc.

Code: Select all

#SingleInstance, Force
SetTitleMatchMode, 2

F10::
	MsgBox, % GetURL("Google Chrome")
	return

GetURL(wTitle*) {
	ErrorLevel := 0
	if !(wId := WinExist(wTitle*)) {
		ErrorLevel := 1
		return
	}
	IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
	DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", wId, "ptr*", elementMain)   ; IUIAutomation::ElementFromHandle
	NumPut(addressbarStrPtr := DllCall("oleaut32\SysAllocString", "wstr", "Address and search bar", "ptr"),(VarSetCapacity(addressbar,8+2*A_PtrSize)+NumPut(8,addressbar,0,"short"))*0+&addressbar,8,"ptr")
	DllCall("oleaut32\SysFreeString", "ptr", addressbarStrPtr)
	if (A_PtrSize = 4) {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "int64", NumGet(addressbar, 0, "int64"), "int64", NumGet(addressbar, 8, "int64"), "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	} else {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "ptr", &addressbar, "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	}
	DllCall(NumGet(NumGet(elementMain+0)+5*A_PtrSize), "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", addressbarCondition, "ptr*", currentURLElement) ; IUIAutomationElement::FindFirst
	DllCall(NumGet(NumGet(currentURLElement+0)+10*A_PtrSize),"ptr",currentURLElement,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+&currentURL) ;IUIAutomationElement::GetCurrentPropertyValue
	ObjRelease(currentURLElement)
	ObjRelease(elementMain)
	ObjRelease(IUIAutomation)
	return StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
}
very fast, can this method be used like acc to get list of all url's in all tabs?

Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 02 May 2022, 12:58

tdalon wrote:
02 May 2022, 00:33
@Descolada : Your approach seems faster than the Acc based recursive one. But it is totally cryptic to me. I would be curious to learn how you've come to it.

I am not 100% sure if the ErrorLevel variable should not be defined as global in the function. Else it wouldn't be returned to the calling script, right?
Hello,
This approach is using the UI Automation framework, which is the successor to what Acc is using. First few lines create the Com object to access UIA and get the element for Chrome. Then I used the Accessibility Insights tool to find the URL bar property name ("Address and search bar") for Chrome, and used that to create a property condition to essentially filter out all properties with that name, then used FindFirst to take the first one. Finally I used GetCurrentPropertyValue to get the value of the URL bar. A nice coincidence was that Edge's URL bar had the exact same property name, so it works for both. For other browsers you can also find out the property name and just replace "Address and search bar" with your found value.
Unfortunately AHK doesn't have a good library for UIA. This is one of the better ones: viewtopic.php?style=17&t=93892, but it needs modifying to work on 32-bit systems too. Some examples of UIA.

I don't think ErrorLevel needs to be declared as global, because built-in variables (same as Clipboard) should act as global. Could be wrong though...
AHKStudent wrote: very fast, can this method be used like acc to get list of all url's in all tabs?

I don't think its possible to get all URLs without clicking through the tabs. But if clicking is allowed then yes, it's possible to get a list of all open tabs, loop through them by activating the tabs, and gathering the URLs.

User avatar
Krutstugan
Posts: 22
Joined: 26 May 2021, 09:56

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

Post by Krutstugan » 06 May 2022, 12:43

I've been using the script in this thread for about a year and lately (within the last week or so), it has not been working. Clicking F8 simply gives me a blank msgbox. Anyone else with this issue?

I have tested:
Microsoft Edge Version 101.0.1210.39 (Official build) (64-bit)
Chrome Version 100.0.4896.127 (Official Build) (64-bit)
Firefox 100.0 (64-bit)

Windows 10 Enterprise 21H1
OS Build 19043.1645

garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

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

Post by garry » 07 May 2022, 14:21

basic example , get > url/ title / marked text

Code: Select all

#If WinActive("ahk_exe chrome.exe")
y:=" - Google Chrome"              ;- delimiter for strsplit

*~$!F12::
clipboard:=""
text:="",text1:=""
sendinput, ^c
clipwait,1,1
if errorlevel=0
 {
 Text:=clipboard
 text1 := RegExReplace(text, "([. ! ? : - = ] )", "$1`r`n")
 }
clipboard:="" 
sleep,500
;-- copy URL ------------
 url:=""
 send,^l
 sleep,500
 send,^c 
 clipwait,1,1
 if errorlevel=0
   {
   url:=clipboard
   sleep,100
   send,^{end}
   }   
clipboard:=""
sleep,500
;------------
 title:=""
 WinGetActiveTitle, title
 a:=StrSplit(title,y)
 title:=a[1]
;------------------------
if text1<>
  msgbox, 262144, ,--------- URL   ----------------`n%url%`n--------- TITLE ----------------`n%title%`n--------- TEXT  ----------------`n%text1%`n================================`n,5
else
  msgbox, 262144, ,--------- URL   ----------------`n%url%`n--------- TITLE ----------------`n%title%`n================================`n,5
return
esc::exitapp

User avatar
Krutstugan
Posts: 22
Joined: 26 May 2021, 09:56

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

Post by Krutstugan » 16 Jun 2022, 01:23

This library suddenly started working again for me. (Win+F8 now displays URL from address bar). Tested and verified on:
Google Chrome 102.0.5005.115 (64-bit)
Microsoft Edge 102.0.1245.41 (64-bit)
Firefox 101.0.1 (64-bit)

I have no clue what have happened. I have not really done anything. And I have been testing intermittently over the last month without success. I still suspect something has changed in my machine. But I'm posting the versions numbers just in case.

User avatar
tdalon
Posts: 41
Joined: 21 Apr 2017, 07:19
Location: Germany
Contact:

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

Post by tdalon » 08 Aug 2022, 00:51

Descolada wrote:
02 May 2022, 12:58
Hello,
This approach is using the UI Automation framework, which is the successor to what Acc is using. First few lines create the Com object to access UIA and get the element for Chrome. Then I used the Accessibility Insights tool to find the URL bar property name ("Address and search bar") for Chrome, and used that to create a property condition to essentially filter out all properties with that name, then used FindFirst to take the first one. Finally I used GetCurrentPropertyValue to get the value of the URL bar. A nice coincidence was that Edge's URL bar had the exact same property name, so it works for both. For other browsers you can also find out the property name and just replace "Address and search bar" with your found value.
Unfortunately AHK doesn't have a good library for UIA. This is one of the better ones: viewtopic.php?style=17&t=93892, but it needs modifying to work on 32-bit systems too. Some examples of UIA.
Hi Descolada
And thanks for the explanation. (I know btw about a good UIA Library now ;-))
I was wondering if this function will only work with a language set to English because you search for the property "Address and search bar".
Any thought about it? If it is language specific it would make the deployment of it very limited :-(
Thank you
Thierry

Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 08 Aug 2022, 03:09

@tdalon, that specific implementation is unfortunately language specific. I can think of two language independent ways, which are easier to implement with UIA_Interface:
1) Use Run, chrome.exe about:blank and then find the first Edit element (not using the name at all)
2) Find all Edit elements, then loop through them and select the one with least top bound value (the smallest Y coordinate), which should be the URL bar. UIA_Browser should do that as a fallback if the URL bar isn't found by name. The drawback is that it is quite slow (though it has to be done just once and later reused)...
3) In Chrome I think the URL bar element is always at the bottom of the tree, so one option I haven't ever tried is getting the last Edit element with FindFirstWithOptions. This would be a Chrome-specific solution.

User avatar
tdalon
Posts: 41
Joined: 21 Apr 2017, 07:19
Location: Germany
Contact:

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

Post by tdalon » 09 Aug 2022, 00:24

@Descolada Maybe you could share here in this thread the answer that would be based upon your UIA library / UIA_Browser.

Code: Select all

#include <UIA_Browser>
...
b := new UIA_Browser()
sUrl := b.GetCurrentURL()

Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 09 Aug 2022, 10:01

@tdalon, sure, here are all the three ideas implemented (requiring only UIA_Interface):

Code: Select all

#Include <UIA_Interface>
MsgBox, % GetURLBar1("ahk_exe chrome.exe").Dump()
MsgBox, % GetURLBar2().Dump()
MsgBox, % GetURLBar3("ahk_exe chrome.exe").Dump()
ExitApp

GetURLBar1(wTitle:="A") {
    static URLBarEl
    if IsObject(URLBarEl) && URLBarEl.CurrentExists
        return URLBarEl
    else {
        allEdits := UIA_Interface().ElementFromHandle(WinExist(wTitle)).FindAllByType("Edit"), topmost := 100000
        for _, editEl in allEdits
            if ((buf := editEl.CurrentBoundingRectangle.t) < topmost) && !editEl.CurrentIsOffscreen
                topmost := buf, URLBarEl := editEl
        return URLBarEl
    }
}

GetURLBar2(exeName:="chrome.exe", closeTabAfter:=True) {
    static URLBarEl
    if IsObject(URLBarEl) && URLBarEl.CurrentExists
        return URLBarEl
    Run, %exeName% about:blank
    WinWaitActive, about:blank
    if (URLBarEl := UIA_Interface().ElementFromHandle(WinExist("A")).FindFirstByType("Edit")) && closeTabAfter
        UIA_Interface().TreeWalkerTrue.GetFirstChildElement(UIA_Interface().CreateTreeWalker(UIA_Interface().CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, UIA_Enum.UIA_TabItemControlTypeId)).GetPreviousSiblingElement(URLBarEl)).Click()
    return URLBarEl
}

GetURLBar3(wTitle:="A") {
    static URLBarEl
    if IsObject(URLBarEl) && URLBarEl.CurrentExists
        return URLBarEl
    else {
        return URLBarEl := UIA_Interface().ElementFromHandle(WinExist(wTitle)).FindFirstWithOptions(0x4, UIA_Interface().CreatePropertyCondition(UIA_Enum.UIA_ControlTypePropertyId, UIA_Enum.UIA_EditControlTypeId), UIA_Enum.TreeTraversalOptions_LastToFirstOrder)
    }
}
For Chrome, the third one is probably the best.

To get/set the current address, use the CurrentValue property: GetURLBar1("ahk_exe chrome.exe").CurrentValue

smogmanus
Posts: 44
Joined: 27 Jul 2015, 12:44

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

Post by smogmanus » 28 Sep 2022, 11:37

Hello,

I love your script. I do not know exactly how you wrote this script but I use it on a hourly basis when I want to capture a web page link and add text to the link. Then I write the results to a file for later use.
bbb-getactiveur2-works.ahk
This is the file I use to get webpage information. I write the results to a file. Then I restart AHK to make the new link active.
(11.11 KiB) Downloaded 236 times

mockroot
Posts: 1
Joined: 09 Jul 2018, 08:10

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

Post by mockroot » 07 Mar 2023, 15:12

Has anyone ported this to v2?

User avatar
DataLife
Posts: 445
Joined: 29 Sep 2013, 19:52

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

Post by DataLife » 15 Jun 2023, 16:55

I am using this function to get the URL of a tab in Edge.

Is there a way to suppress ACC error messages?

My script is designed to continue on even if the URL can not be retrieved, but I would like to suppress this error message.

Error: 0x80004005 - Unspecified error
Source: (null)
Description: (null)
HelpFile: (null)
HelpContext: 0

Specifically: accChildCount

Line#
1375: Return,ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
1376: }
1377: {
1378: if ComObjType(Acc,"Name") != "IAccessible"
1379: ErrorLevel := "Invalid IAccessible Object"
1380: Else
1380: {
---> 1381: Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
1382: 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
1382: {
1383: Loop,%cChildren%
1384: 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):
1385: Return,Children.MaxIndex()?Children:
1386: }
1386: Else

Continue running the script?
---------------------------
Yes No
---------------------------
Last edited by DataLife on 15 Jun 2023, 21:53, edited 2 times in total.
Check out my scripts. (MyIpChanger) (ClipBoard Manager) (SavePictureAs)
All my scripts are tested on Windows 10, AutoHotkey 32 bit Ansi unless otherwise stated.

User avatar
DataLife
Posts: 445
Joined: 29 Sep 2013, 19:52

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

Post by DataLife » 15 Jun 2023, 20:53

JoeSchmoe wrote:
21 Feb 2016, 13:58
I just got the exact same error again (I checked and the screenshots are identical). This time it happened in Chrome when I closed a Google Calendar tab and it switched to a Google drive tab.

A hypothesis would be that the problem arises from the following code:

Code: Select all

	For nChild, accChild in Acc_Children(accObj)
		If IsObject(accAddressBar := GetAddressBar(accChild))
			Return accAddressBar
As it is looping through Acc_Children(accObj), accObj might be changing, leading to an inconsistent state. In other words, if the browser is redirected (as in my Feb 18 post) or a window is closed (as in today's post) while the code is looping through the above loop, it attempts to access a key-value pair that no longer exists. Acc_Children is called within the above loop, and that is where it crashes.

Perhaps it could be fixed by checking to see if the state is still consistent around line 116? Line 116 is shown in the screenshot - that's where it crashes.

I seem to get an error every 3 days or so and so I'm thinking of asking for help in the Ask for Help subforum, as error 0x80004005 seems to be a pretty deep COM error and they may be able to help with it. If anyone else has any thoughts at all, I'd love to hear them.

Edit: happened again on 2/22 and 2/23
Did you find a solution for this? I also have this issue.
Check out my scripts. (MyIpChanger) (ClipBoard Manager) (SavePictureAs)
All my scripts are tested on Windows 10, AutoHotkey 32 bit Ansi unless otherwise stated.

newcod3r
Posts: 505
Joined: 30 Sep 2021, 02:16

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

Post by newcod3r » 25 Jun 2023, 21:13

Descolada wrote:
02 May 2022, 12:58
tdalon wrote:
02 May 2022, 00:33
@Descolada : Your approach seems faster than the Acc based recursive one. But it is totally cryptic to me. I would be curious to learn how you've come to it.

I am not 100% sure if the ErrorLevel variable should not be defined as global in the function. Else it wouldn't be returned to the calling script, right?
Hello,
This approach is using the UI Automation framework, which is the successor to what Acc is using. First few lines create the Com object to access UIA and get the element for Chrome. Then I used the Accessibility Insights tool to find the URL bar property name ("Address and search bar") for Chrome, and used that to create a property condition to essentially filter out all properties with that name, then used FindFirst to take the first one. Finally I used GetCurrentPropertyValue to get the value of the URL bar. A nice coincidence was that Edge's URL bar had the exact same property name, so it works for both. For other browsers you can also find out the property name and just replace "Address and search bar" with your found value.
Unfortunately AHK doesn't have a good library for UIA. This is one of the better ones: viewtopic.php?style=17&t=93892, but it needs modifying to work on 32-bit systems too. Some examples of UIA.

I don't think ErrorLevel needs to be declared as global, because built-in variables (same as Clipboard) should act as global. Could be wrong though...
AHKStudent wrote: very fast, can this method be used like acc to get list of all url's in all tabs?

I don't think its possible to get all URLs without clicking through the tabs. But if clicking is allowed then yes, it's possible to get a list of all open tabs, loop through them by activating the tabs, and gathering the URLs.
Hi @Descolada,

I have been using your getUrl script for many months and it has been working perfectly, but recently it has stopped detecting URLs. Any idea what I can do to fix it please?

Code: Select all

GetUrl(wTitle:="Google Chrome") { ; best working get url tool!

	ErrorLevel := 0
	if !(wId := WinExist(wTitle)) {
		ErrorLevel := 1
		return
	}
	IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
	DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", wId, "ptr*", elementMain)   ; IUIAutomation::ElementFromHandle
	NumPut(addressbarStrPtr := DllCall("oleaut32\SysAllocString", "wstr", "Address and search bar", "ptr"),(VarSetCapacity(addressbar,8+2*A_PtrSize)+NumPut(8,addressbar,0,"short"))*0+&addressbar,8,"ptr")
	DllCall("oleaut32\SysFreeString", "ptr", addressbarStrPtr)
	if (A_PtrSize = 4) {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "int64", NumGet(addressbar, 0, "int64"), "int64", NumGet(addressbar, 8, "int64"), "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	} else {
		DllCall(NumGet(NumGet(IUIAutomation+0)+23*A_PtrSize), "ptr", IUIAutomation, "int", 30005, "ptr", &addressbar, "ptr*", addressbarCondition)   ; IUIAutomation::CreatePropertyCondition
	}
	DllCall(NumGet(NumGet(elementMain+0)+5*A_PtrSize), "ptr", elementMain, "int", TreeScope_Descendants := 0x4, "ptr", addressbarCondition, "ptr*", currentURLElement) ; IUIAutomationElement::FindFirst
	DllCall(NumGet(NumGet(currentURLElement+0)+10*A_PtrSize),"ptr",currentURLElement,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+&currentURL) ;IUIAutomationElement::GetCurrentPropertyValue
	ObjRelease(currentURLElement)
	ObjRelease(elementMain)
	ObjRelease(IUIAutomation)
    sUrl := StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
    If !sUrl { ;empty
        ErrorLevel := 1
        return
    }

    If !RegExMatch(sUrl,"^https?://")
        sUrl := "https://" . sUrl
	return sUrl
}

Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 26 Jun 2023, 09:09

@newcod3r, it's working fine in my setup (latest Chrome, Windows 10).
1) The name of the function is deceptive: it's not designed to get the URL of *any* browser, it will only in browsers where the address bar element is named "Address and search bar" (this is true in Chrome with language set to English).
2) The standalone function is missing code for accessibility activation, which sometimes is not automatic. In Chrome you can check whether accessibility is enabled by navigating to chrome://accessibility/
3) Check whether the address bar element is still named "Address and search bar" with UIAViewer or Accessibility Insights. If it is not, then change the name accordingly in the code.
4) You might find working GetURL functions from this GitHub gist.
5) Also this modified GetURL might work (at least for Chrome):

Code: Select all

GetUrl(wTitle:="ahk_exe chrome.exe") {
	ErrorLevel := 0
	if !(wId := WinExist(wTitle)) {
		ErrorLevel := 1
		return
	}
    try ControlGet, cHwnd, Hwnd,, Chrome_RenderWidgetHostHWND1, ahk_id %wId%
    if !cHwnd {
		ErrorLevel := 2
		return
    }
    SendMessage, WM_GETOBJECT := 0x003D, 0, 1, , ahk_id %cHwnd%
	IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
	DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", cHwnd, "ptr*", documentEl)   ; IUIAutomation::ElementFromHandle
	DllCall(NumGet(NumGet(documentEl+0)+10*A_PtrSize),"ptr",documentEl,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+&currentURL) ;IUIAutomationElement::GetCurrentPropertyValue
	ObjRelease(documentEl)
	ObjRelease(IUIAutomation)
    sUrl := StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
    DllCall("oleaut32\SysFreeString", "ptr", currentURL)
    If !sUrl { ;empty
        ErrorLevel := 3
        return
    }
	return sUrl
}

newcod3r
Posts: 505
Joined: 30 Sep 2021, 02:16

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

Post by newcod3r » 26 Jun 2023, 21:20

2:
image.png
image.png (57.83 KiB) Viewed 3304 times
[

3:
image.png
image.png (39.46 KiB) Viewed 3304 times
5: have tried the updated script and when tested using msgbox, it returns blank in URL variable.

Descolada
Posts: 1098
Joined: 23 Dec 2021, 02:30

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

Post by Descolada » 26 Jun 2023, 23:13

@newcod3r, in the chrome://accessibility/ site try checking "Screen reader support". Also make sure that when you run the GetURL function that the Chrome browser is at least partially visible - otherwise UIA methods won't work. Also, what is the ErrorLevel after the function? Try running this and output the result:

Code: Select all

WinActivate, % "ahk_exe chrome.exe"
WinWaitActive, % "ahk_exe chrome.exe",, 1
MsgBox % GetUrl("ahk_exe chrome.exe") "`nErrorLevel: " ErrorLevel 

GetUrl(wTitle:="ahk_exe chrome.exe") {
	ErrorLevel := 0
	if !(wId := WinExist(wTitle)) {
		ErrorLevel := 1
		return
	}
    try ControlGet, cHwnd, Hwnd,, Chrome_RenderWidgetHostHWND1, ahk_id %wId%
    if !cHwnd {
		ErrorLevel := 2
		return
    }
    SendMessage, WM_GETOBJECT := 0x003D, 0, 1, , ahk_id %cHwnd%
	IUIAutomation := ComObjCreate(CLSID_CUIAutomation := "{ff48dba4-60ef-4201-aa87-54103eef594e}", IID_IUIAutomation := "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
	DllCall(NumGet(NumGet(IUIAutomation+0)+6*A_PtrSize), "ptr", IUIAutomation, "ptr", cHwnd, "ptr*", documentEl)   ; IUIAutomation::ElementFromHandle
	DllCall(NumGet(NumGet(documentEl+0)+10*A_PtrSize),"ptr",documentEl,"uint",30045,"ptr",(VarSetCapacity(currentURL,8+2*A_PtrSize)+NumPut(0,currentURL,0,"short")+NumPut(0,currentURL,8,"ptr"))*0+&currentURL) ;IUIAutomationElement::GetCurrentPropertyValue
	ObjRelease(documentEl)
	ObjRelease(IUIAutomation)
    sUrl := StrGet(NumGet(currentURL,8,"ptr"),"utf-16")
    DllCall("oleaut32\SysFreeString", "ptr", currentURL)
    If !sUrl { ;empty
        ErrorLevel := 3
        return
    }
	return sUrl
}

Post Reply

Return to “Scripts and Functions (v1)”