Code: Select all
ControlSend, , ^l, A
Sleep, 100
MsgBox, % GetUrl("A")
Code: Select all
ControlSend, , ^l, A
Sleep, 100
MsgBox, % GetUrl("A")
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+¤tURL) ;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
}
very fast, can this method be used like acc to get list of all url's in all tabs?Descolada wrote: ↑29 Apr 2022, 03:06Tested 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+¤tURL) ;IUIAutomationElement::GetCurrentPropertyValue ObjRelease(currentURLElement) ObjRelease(elementMain) ObjRelease(IUIAutomation) return StrGet(NumGet(currentURL,8,"ptr"),"utf-16") }
Hello,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?
AHKStudent wrote: very fast, can this method be used like acc to get list of all url's in all tabs?
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
Hi DescoladaDescolada wrote: ↑02 May 2022, 12:58Hello,
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.
Code: Select all
#include <UIA_Browser>
...
b := new UIA_Browser()
sUrl := b.GetCurrentURL()
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)
}
}
Did you find a solution for this? I also have this issue.JoeSchmoe wrote: ↑21 Feb 2016, 13:58I 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: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.Code: Select all
For nChild, accChild in Acc_Children(accObj) If IsObject(accAddressBar := GetAddressBar(accChild)) Return accAddressBar
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
Hi @Descolada,Descolada wrote: ↑02 May 2022, 12:58Hello,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?
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.
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+¤tURL) ;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
}
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+¤tURL) ;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
}
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+¤tURL) ;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
}
Return to “Scripts and Functions (v1)”
Users browsing this forum: gwarble and 48 guests