AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Basic Webpage Controls with JavaScript / COM - Tutorial
Goto page Previous  1, 2, 3, ... 15, 16, 17  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  

Do you think this tutorial is beneficial to the AHK Community?
Yeah, I think this tutorial is a great value-add to the Community.
86%
 86%  [ 91 ]
Nope - I think this tutorial is a waste of web space.
0%
 0%  [ 1 ]
I think this tutorial would be better if it incorporated AHK_L & COM_L.
12%
 12%  [ 13 ]
Total Votes : 105

Author Message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Nov 14, 2009 6:33 am    Post subject: Reply with quote

I suggest to refer to Internet Explorer Architecture.
And, yes, tank's code will work. If already obtained pwb, however, it's a bit pointless to go through that step, IMO. My suggestion was to demonstrate the means to obtain directly Window or Document objects and start from them. Obtaining Document object has been used many times in the forum, but obtaining Window object has been used little.
http://www.autohotkey.com/forum/viewtopic.php?t=19256&start=28

Code:
pacc := COM_AccessibleObjectFromWindow(hIESrv) ; window handle of Internet Explorer_Server
pwin := COM_QueryService(pacc, "{332C4427-26CB-11D0-B483-00C04FD90119}")
COM_Release(pacc)
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Sat Nov 14, 2009 6:39 am    Post subject: Reply with quote

@Sean the reason I avoid this method is because it requires the tab to be the active one. Obtaining the pwb avoids this and allows multiple tabs within a single browser to be automated without regard to being selected or not

However you are correct if it doesn’t matter if the tab is the active one yours is more direct to the point.

I might also suggest that in my own production environment with 300’ish users that this (MSAA) method can fail (not often and not consistently). I have yet to identify why. Embarassed This is the other reason checking the shellWindows collection is my preferred choice
Wink

I will point out i hadnt seen AccessibleObjectFromPoint demonstrated any where else and my knowledge of MSAA is very weak

The iweb functions are the effort of 2 years attempting to get the best stability with ahk to automate on clients spread across 3 physical sites wehre the end user can also mess things up in browser settings. They are not full proof by any means but i Saw a 60+ percent drop in automation failure reports when I moved accessability out of the equation
_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Nov 14, 2009 7:44 am    Post subject: Reply with quote

tank wrote:
@Sean the reason I avoid this method is because it requires the tab to be the active one.
This method doesn't require the tab to be the active one. It just needs to obtain the correct window handle of the corresponding Internet Explorer_Server which I agree may sometimes be hard to identify in practice though.

Quote:
I might also suggest that in my own production environment with 300’ish users that this (MSAA) method can fail (not often and not consistently). I have yet to identify why. Embarassed This is the other reason checking the shellWindows collection is my preferred choice
Wink
Yes, MSAA is too old, I also found it awkward often. Anyway, I didn't suggest to replace already established methods with this, just demonstration that it's possible when mentioning conceptually Window object is the top level one in DOM.

Quote:
I will point out i hadnt seen AccessibleObjectFromPoint demonstrated any where else
IIRC, I used it many times in the posted scripts. Anyway it may be useful to obtain directly IHTMLElement in DOM. As a matter of fact, my first plan for IE HTML Element Spy was utilizing it, however, it didn't provide the fine granularity needed, so I took a different/current route.

Quote:
The iweb functions are the effort of 2 years attempting to get the best stability with ahk to automate on clients spread across 3 physical sites wehre the end user can also mess things up in browser settings. They are not full proof by any means but i Saw a 60+ percent drop in automation failure reports when I moved accessability out of the equation
Oh I see. Thanks for valuable info that I can't possibly gain myself.
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Sat Nov 14, 2009 8:29 am    Post subject: Reply with quote

Sean wrote:
Yes, MSAA is too old, I also found it awkward often. Anyway, I didn't suggest to replace already established methods with this, just demonstration that it's possible when mentioning conceptually Window object is the top level one in DOM.
I am glad you did i forgot about it since I abandoned ahklerners injectJS function
Sean wrote:
This method doesn't require the tab to be the active one. It just needs to obtain the correct window handle of the corresponding Internet Explorer_Server which I agree may sometimes be hard to identify in practice though.
Can you think of any that don’t require it to be the top most tab?
Sean wrote:
Oh I see.
FYI though I wrote them I have yet to widely use iWeb_clickHref iWeb_clickValue Mostly I use the iWeb_getwin and the iWeb_setDomObj and iWeb_getDomObj functions. so the others aren’t well tested
Sean wrote:
Anyway it may be useful to obtain directly IHTMLElement in DOM.
At any rate I see how its useful to retrieve info with this but am unsure how one would go about using it in a larger script that uses multiple pages and or sites.
The reason for iWeb_DomWin is because there are in limited cases sites where there are script permissions and doing this bypass that security restriction I believe its related to the security zone setting allow websites to use restricted protocols for active content But I cant prove it

It seems we mainly agree on the point of using the pwb might be the most effective way to go even if it isn’t the only way
Another way to grab an element would be to try and find unique text and possibly request an offset of elements using the find method. Since this method traverses frames if unique text is avail it may be the easiest for users to use with minimal understanding of DOM and no understanding of JavaScript

There have been members of our team new to scripting that rely on this for the automation jobs
Code:
element:=IE_Find("Some unique text")
Com_invoke(element,"click")

IE_Find(needle,win="A",property="",offset=0)
{
   If   (win=="A")
      WinGetTitle,win,%win% ahk_class IEFrame
   StringSplit,wins,win,-
   _autotrim:=A_AutoTrim
   AutoTrim,On   
   wins1=%wins1%
   AutoTrim,%_autotrim%
   If   psh   :=   COM_CreateObject("Shell.Application") {
      If   psw   :=   COM_Invoke(psh,   "Windows") {
         Loop, %   COM_Invoke(psw,   "Count")
            If   pwb   :=   (InStr(COM_Invoke(psw,"Item[" A_Index-1 "].LocationName"),wins1)   && InStr(COM_Invoke(psw,"Item[" A_Index-1 "].FullName"), "iexplore.exe")) ? COM_Invoke(psw,"Item", A_Index-1) :
               Break
         COM_Release(psw)
      }
      COM_Release(psh)
   }
   If   !pwb
      Return
   If   !pWin:=COM_QueryService(pwb,   "{332C4427-26CB-11D0-B483-00C04FD90119}",   "{332C4427-26CB-11D0-B483-00C04FD90119}")
   {
      COM_Release(pwb)
      Return
   }   
   If   oRange:=COM_Invoke(pWin,"document.body.createTextRange")
   {
      COM_Invoke(oRange,"findText",needle)
      _res:=property ? COM_Invoke(pWin,"Document.all.item[" COM_Invoke(oRange,"parentElement.sourceIndex")+offset "]." property) :  COM_Invoke(pWin,"Document.all.item", COM_Invoke(oRange,"parentElement.sourceIndex")+offset)
      COM_Release(oRange)
   }   
   COM_Release(pWin)
   COM_Release(pwb)
   Return   _res
}

_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Nov 14, 2009 12:35 pm    Post subject: Reply with quote

tank wrote:
Can you think of any that don’t require it to be the top most tab?
It can be used sort of as the replacement of ShellWindows whose cons is that it requires Explorer shell. As I switched to 64bit Win7 a few days ago, I became curious and tested it also on 64bit IE8 on 64bit Win7, it still worked flawlessly.
Code:
DetectHiddenWindows, On
WinGet, ControlList, ControlList, ahk_class IEFrame
RegExMatch(ControlList, "(?<=Internet Explorer_Server)\d+(?!.*Internet Explorer_Server)", nCount)
Loop, %   nCount
{
   ControlGet, hWnd, hWnd,, Internet Explorer_Server%A_Index%, ahk_class IEFrame
   window := COM_Enwrap(COM_QueryService(COM_AccessibleObjectFromWindow(hWnd), "{332C4427-26CB-11D0-B483-00C04FD90119}"))
;   oWeb := COM_Enwrap(COM_QueryService(window, "{0002DF05-0000-0000-C000-000000000046}"))
   MsgBox % window.document.url
}

Quote:
The reason for iWeb_DomWin is because there are in limited cases sites where there are script permissions and doing this bypass that security restriction I believe its related to the security zone setting allow websites to use restricted protocols for active content But I cant prove it
OK, I see your point. I also had to do the similar for cross domains across frames in IE HTML Element Spy script.
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Sat Nov 14, 2009 6:32 pm    Post subject: Reply with quote

Very interesting Sean i learned something from you that i previously hadnt known (as usual) For the sake of learing im gonna play with the code you have as it relates to IE 7(i hope) as well
_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Mon Nov 16, 2009 3:06 am    Post subject: Reply with quote

Jethrow given some recent questions since I have used these methods on all of the OS's and browsers including Vista and 7

COM DOM and HTML are Industry Standards They are supported in IE versions 4.0 and up and I have tested AHK and Sean's COM library on Windows 2k XP Vista and 7 as well as each of the versions of IE(I had 4.0 on a Bart PE implementation for a while) Obviously tabs were only introduced as of IE7. If COM does not work for your web automation needs it is not specifically related to the browser version or OS. It could perhaps be due to BHO's common in my workplace as a problem or specific security settings in a corp. environment.
BHO’s by far make up the majority of the items that cause COM to fail to automate a browser when the code is correct. Usually the interference is in the form of creating hidden framesets. The most common I encounter in a secure environment is OWS which comes with office and is a BHO for SharePoint. Some Antivirus install BHO's as well but as of yet I have not seen those create such a problem
_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Tue Nov 17, 2009 3:21 am    Post subject: Reply with quote

the iWebBrowser2 Learner has been updated to give example iWeb function calls with frame references
the iWeb functions have been updated to allow frame references and bypass cross domain restrictions I made this update only because Sinkfaze put so much effort himself into trying



I also noticed a bug and corrected it with identifying the page title
_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
UncleScrooge



Joined: 14 Apr 2009
Posts: 75
Location: Italy

PostPosted: Mon Nov 30, 2009 1:04 pm    Post subject: Reply with quote

Hi all

and compliments for the job done, even though I often understand less tan 30% of it... but it had been very stimulating: spent a couple of evenings surfing through HTML DOM learning pages at W3Schools.

wouldnt bother anybody with stupid questions but I'm stuck in this:

I got the Sean function IE_DocumentComplete working flawlessly to get my particular URL open
Code:
sUrl :=   "http://127.0.0.1:81/Upload.html"
COM_Init()
pweb :=   COM_CreateObject("InternetExplorer.Application")
sink :=   COM_ConnectObject(pweb, "IE_")
bComplete := False
COM_Invoke(pweb, "Navigate", sUrl)
While !bComplete
      Sleep, 500
MsgBox, 36, , Do you want it visible?
IfMsgBox, Yes
   COM_Invoke(pweb, "Visible", True)

I work in industrial automation - process control and our controllers' network exchange informations thru a MODBUS and interface with the outer world via a WEB server (each controller owns one).
Here the address h t t p :// 127.0.0.1:81/ refers to a controller simulator running on my PC. The "Upload.html" document is the user interface to handle files back and forth:



now, before I start doing anything at all, as Sean'function tells me that the url loading procedures has terminated, I want to make it sure the document is showing me the expected things. This will also tell me that I'm really communicating to a controller (each controller owns a document such as http:\\xxx.xxx.xxx.xxx\Upload.html, if the document doesn't load up correctly we might have a network problem -cabling or else).
So I thought the easiest way was to check if the browser can return the document header contents (<h1>) that I know to be:
File management
(see fig)

As shown earlier in this post I imagined it would had been easy to ask the IE object to retrieve it, and in fact when I try to inject javascript through the URL address control like this:
Code:
javascript:alert(document.getElementsByTagName("h1")[0].innerHTML)

I got the message box beeping me: "File management"
wow: I figured it was a piece o'cake to push it in my AHK as suggested like this:
Code:
MsgBox % COM_Invoke(pwb, "document.getElementsByTagName([h1]).item[0].innerHTML")

no such luck... all I got is a barrage of messages from COM telling that all the components (functions) of the COM_Invoke param (document getElementsByTagName item and innerHTML cannot be found:



what am I doing wrong?
thnx for any answer

Ps: I've tried all the variants:
Code:
document.getElementsByTagName[h1].item[0].innerHTML
document.getElementsByTagName[h1][0].innerHTML

with no better results: all I got is a higher or lower number of error messages from COM


Last edited by UncleScrooge on Mon Nov 30, 2009 5:46 pm; edited 2 times in total
Back to top
View user's profile Send private message AIM Address
sinkfaze



Joined: 18 Mar 2008
Posts: 5044
Location: the tunnel(?=light)

PostPosted: Mon Nov 30, 2009 1:44 pm    Post subject: Reply with quote

Try this:

Code:
COM_Invoke(pwb,"document.all[h1].innerHTML")

_________________
Try Quick Search for Autohotkey or see the tutorial for newbies.
Back to top
View user's profile Send private message Send e-mail
tank



Joined: 21 Dec 2007
Posts: 3700
Location: Louisville KY USA

PostPosted: Mon Nov 30, 2009 1:52 pm    Post subject: Reply with quote

sinkfaze wrote:
Try this:

Code:
COM_Invoke(pwb,"document.all[h1].innerHTML")
um h1 is a tag not an id so that shouldnt work
Code:
COM_Invoke(pwb,"document.all.tags[h1].item[0].innerHTML")

Code:
COM_Invoke(pwb,"document.getElementsByTagName[h1].item[0].innerHTML")
should simlarly work but havent tested it
_________________

We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Back to top
View user's profile Send private message
sinkfaze



Joined: 18 Mar 2008
Posts: 5044
Location: the tunnel(?=light)

PostPosted: Mon Nov 30, 2009 2:01 pm    Post subject: Reply with quote

tank wrote:
um h1 is a tag not an id so that shouldnt work


Ugh...and I read that before I answered, too...sorry.
_________________
Try Quick Search for Autohotkey or see the tutorial for newbies.
Back to top
View user's profile Send private message Send e-mail
jethrow



Joined: 24 May 2009
Posts: 1907
Location: Iowa, USA

PostPosted: Mon Nov 30, 2009 2:09 pm    Post subject: Reply with quote

UncleScrooge wrote:
all I got is a barrage of messages from COM telling that all the components (functions) of the COM_Invoke param (document getElementsByTagName item and innerHTML cannot be found
... Ps: I've tried all the variants:
Code:
document.getElementsByTagName[h1].item[0].innerHTML
document.getElementsByTagName[h1][0].innerHTML

with no better results: all I got is a higher or lower number of error messages from COM
If you are getting a COM Error when trying to invoke the document object, the document isn't accessible (perhaps not loaded).

UncleScrooge wrote:
Code:
sUrl :=   "http://127.0.0.1:81/Upload.html"
COM_Init()
pweb :=   COM_CreateObject("InternetExplorer.Application")
sink :=   COM_ConnectObject(pweb, "IE_")
bComplete := False
COM_Invoke(pweb, "Navigate", sUrl)
While !bComplete
      Sleep, 500
MsgBox, 36, , Do you want it visible?
IfMsgBox, Yes
   COM_Invoke(pweb, "Visible", True)
If this is all your code, you aren't using Sean's DocumentComplete method correctly. Please post all your code (or at least all your code that is relevant - ie. How is your While-loop breaking?).
_________________
Very Happy - in case I forgot to smile
Basic Webpage Controls
COM Object Reference
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
UncleScrooge



Joined: 14 Apr 2009
Posts: 75
Location: Italy

PostPosted: Mon Nov 30, 2009 5:07 pm    Post subject: Reply with quote

jethrow wrote:
...........
If this is all your code, you aren't using Sean's method correctly. Please post all your code (or at least all your code that is relevant - ie. How is your While-loop breaking?).


no, obviuosly not. sorry my mistake, here is the complete thing.
Code:

#Persistent
sUrl :=   "http://127.0.0.1:81/Upload.html"
COM_Init()
pweb :=   COM_CreateObject("InternetExplorer.Application")
sink :=   COM_ConnectObject(pweb, "IE_")
bComplete := False
COM_Invoke(pweb, "Navigate", sUrl)
While !bComplete
      Sleep, 500
MsgBox, 36, , Do you want it visible?
IfMsgBox, Yes
   COM_Invoke(pweb, "Visible", True)

;MsgBox % COM_Invoke(pwb, "document.getElementsByTagName[h1][0].innerHTML")
;MsgBox % COM_Invoke(pwb,"document.all.tags[h1].item[0].innerHTML")
MsgBox % COM_Invoke(pwb,"document.getElementsByTagName[h1].item[0].innerHTML")
MsgBox, 36, , Do you want to close it?
IfMsgBox, Yes
   COM_Invoke(pweb, "Quit")

COM_DisconnectObject(sink)
COM_Release(pweb)
COM_Term()
#q::ExitApp     ;WIN key + q to terminate this script
Return

OnComplete:
bComplete := True
Return

IE_DocumentComplete(prms, sink)
{
   If   NumGet(NumGet(prms+0)+24) = NumGet(sink+12)
      SetTimer, OnComplete, -10
/* more rigorous way
   COM_Release(punk1:=COM_QueryInterface(NumGet(NumGet(prms+0)+24),0))
   COM_Release(punk2:=COM_QueryInterface(NumGet(sink+12),0))
   If   (punk1 = punk2)
      SetTimer, OnComplete, -10
*/
}

IEReady(hIESvr = 0)
{
   If Not   hIESvr
   {
      Loop,   50
      {
         ControlGet, hIESvr, hWnd, , Internet Explorer_Server1, A ; ahk_class IEFrame
         If   hIESvr
            Break
         Else   Sleep 100
      }
      If Not   hIESvr
         Return   """Internet Explorer_Server"" Not Found."
   }
   Else
   {
      WinGetClass, sClass, ahk_id %hIESvr%
      If Not   sClass == "Internet Explorer_Server"
         Return   "The specified control is not ""Internet Explorer_Server""."
   }

   COM_Init()
   If   DllCall("SendMessageTimeout", "Uint", hIESvr, "Uint", DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT"), "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 1000, "UintP", lResult)
   &&   DllCall("oleacc\ObjectFromLresult", "Uint", lResult, "Uint", COM_GUID4String(IID_IHTMLDocument2,"{332C4425-26CB-11D0-B483-00C04FD90119}"), "int", 0, "UintP", pdoc)=0
   &&   pdoc && pweb:=COM_QueryService(pdoc,IID_IWebBrowserApp:="{0002DF05-0000-0000-C000-000000000046}")
   {
      While,   COM_Invoke(pweb, "ReadyState") <> 4
      Sleep,   500
      While,   COM_Invoke(pweb, "document.readyState") <> "complete"
      Sleep,   500
      COM_Release(pweb)
   }
   COM_Release(pdoc)
   COM_Term()
   Return   pweb ? "DONE!" : False
}


that line in red is actually quitting the browser session so I guess the pwb object is open and responding correctly... not when I try to access the document though. and as you can see by the commented lines not even tank's suggestions work (btw I love that pissed off Yoda. just great)
the code on top (autoexec section) is of course just a bunch of lines to test functionalities so to manipulate IE (the finished code shouldn't even make IE object visible).

I've tried these and they work wonders (of-bloody-course):
Code:

;js_Snippet = javascript`:document`.getElementsByTagName`(`"h1`"`)`[0`]`.innerHTML`;
js_Snippet = javascript`:alert`(document`.getElementsByTagName`(`"h1`"`)`[0`]`.innerHTML`)`;
COM_Invoke(pweb, "Navigate", js_Snippet)

which I seem to understand means that, since pweb (the IE object) works fine, I need another handle to reference the document object to start using its exposed functions (properties and methods).
Am I getting it right?...
_________________
Intel Centrino @ 2.8GHz
4 GB RAM
WIN XP SP3
Back to top
View user's profile Send private message AIM Address
jethrow



Joined: 24 May 2009
Posts: 1907
Location: Iowa, USA

PostPosted: Mon Nov 30, 2009 5:18 pm    Post subject: Reply with quote

Shocked - Why are you using pweb & pwb? Should be:
Code:
MsgBox % COM_Invoke(pweb,"document.getElementsByTagName[h1].item[0].innerHTML")

On a side-note, this might be a little simpler for your javascript:
Code:
js_Snippet := "javascript:alert(document.getElementsByTagName('h1')[0].innerHTML)"

_________________
Very Happy - in case I forgot to smile
Basic Webpage Controls
COM Object Reference
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, ... 15, 16, 17  Next
Page 2 of 17

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group