Help with controlling Internet Explorer Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Crashm87
Posts: 48
Joined: 25 Jul 2016, 13:12

Help with controlling Internet Explorer

18 Jan 2017, 12:08

Hello.

Sort of new here, been lurking in the wings for years, and I am stuck hoping someone can give me hand.

I am trying to automate a repetitive task for work using DOM in internet explorer. I can't for the life of me get my 'number' to fill into an element on IE.

I am using IE 11. The inspect element is.

<input name="claimNo" class="bodyText" id="claimNo" type="Text" size="10" maxlength="6" value="" lpcachedvisval="1" lpcachedvistime="1484754693">.

I tried writing a basic script to test, and it doesn't work.

Code: Select all

#SingleInstance force
#NoTrayIcon


wb := ComObjCreate("InternetExplorer.Application")
wb.Visible := true
wb.Toolbar := False
wb.Navigate("work_URL")


while wb.busy 
 
sleep, 100 

Sleep, 1000

workorder_number := wb.document.getElementById("claimNo")

workorder_number.Value := 123456

So, before writing all of my code, I tried simply controlling the webpage with the console built in.
Using the console in IE11, I type, document.getElementByID("claimNo").value = 123456;
I get error Unable to set property 'value' of undefined or null reference

Out of curiousity. I loaded my webpage into Google Chrome, and tried the exact same process, and it fills in the 'claimNo' element no problem. Is there something I am missing? Can anyone help me?

I hope I have provided enough information.

Justin
enter8
Posts: 102
Joined: 05 May 2016, 16:48

Re: Help with controlling Internet Explorer

19 Jan 2017, 17:18

In the past, I've only used comobject to get properties, and never to set them, but I just put this together:

Code: Select all

wb := ComObjCreate("InternetExplorer.Application")
wb.Visible := true
wb.Navigate("http://www.worldslongestwebsite.com/")
While wb.busy
   Sleep, 5

param := wb.document.getElementsByClassName("footer")[0]

param.innerHTML := 123456
and it works. It sets the footer to 123456

I'm curious, if 'value' isn't blank, does

Code: Select all

workorder_number := wb.document.getElementById("claimNo").Value
msgbox % workorder_number
return the value from 'value?'
Crashm87
Posts: 48
Joined: 25 Jul 2016, 13:12

Re: Help with controlling Internet Explorer

21 Jan 2017, 09:28

This seems to return a blank Msgbox. I'm not sure I am activating the page correctly, I can't get .Visible to bring the page forward.

Here is my current snippet;

Code: Select all

IEGet( name="" )
{
   IfEqual, Name,, WinGetTitle, Name, ahk_class IEFrame ; Get active window if no parameter
   Name := ( Name="New Tab - Windows Internet Explorer" ) ? "about:Tabs" : RegExReplace( Name, " - (Windows|Microsoft) Internet Explorer" )
   For pwb in ComObjCreate( "Shell.Application" ).Windows
      If ( pwb.LocationName = Name ) && InStr( pwb.FullName, "iexplore.exe" )
         Return pwb
}

while (wb.busy or wb.ReadyState != 4)
    sleep 100

Sleep, 1000
f3::
wb:= IEGet("work_site")  ;this is copied right from URL bar in IE
wb.Visible := true
workorder_number := wb.document.getElementById("claimNo").Value
msgbox %workorder_number%
enter8
Posts: 102
Joined: 05 May 2016, 16:48

Re: Help with controlling Internet Explorer  Topic is solved

21 Jan 2017, 22:31

Step 1: If you haven't already, outside of AHK, open IE and load your page, just to make sure your page loads correctly.

Step 2: I'm not familiar with IEGet. Is this an attempt to open the page in an already opened browser? It may be a great function, but, until you get the simple stuff working, I'd stick to the ComObjCreate approach you were working with before. Use the script you had before but with the attempt to get the element rather than set it.

Code: Select all

#SingleInstance force
#NoTrayIcon

wb := ComObjCreate("InternetExplorer.Application")
wb.Visible := true
wb.Toolbar := False
wb.Navigate("work_URL")

while wb.busy 
 
sleep, 100 

Sleep, 1000

workorder_number := wb.document.getElementById("claimNo").Value
msgbox %workorder_number%
If the page loads in IE, then it will, at a minimum, load and be visible. If the getElement fails, open IE (outside ahk), load your page, right click the element and choose 'inspect element.' That will bring up the DOM explorer and console. The DOM explorer will give you an idea of where your element exists in the page's hierarchy. This can be helpful, if say, the element is inside a frame, as the frame may need to be incorporated into your javascript.

Beyond looking at the DOM Explorer, you'll want to try a few different variables of your javascript in the console. I've spent a lot of time in the console tweaking a line of javascript, seeing what result it gave me, and then tweaking it again. For instance, sometime you have to use 'getAttribute' to get an attribute. I'm not saying this will work, but you could try (in the console):

document.getElementById("claimNo").getAttribute("value")

I'd like to say that I fully understand the DOM, but most of the time it's educated guessing. I generally find it helpful to get the larger stuff, and then work your way down, such as trying something along the lines of

document.getElementById("claimNo").innerHTML

It also might help to see if you can grab a parent node of the element you're trying to get.

Btw, what version of IE are you working with? These types of scripts will only work on version 9 and up.
Crashm87
Posts: 48
Joined: 25 Jul 2016, 13:12

Re: Help with controlling Internet Explorer

27 Jan 2017, 15:42

enter8 wrote:Step 1: If you haven't already, outside of AHK, open IE and load your page, just to make sure your page loads correctly.

Step 2: I'm not familiar with IEGet. Is this an attempt to open the page in an already opened browser? It may be a great function, but, until you get the simple stuff working, I'd stick to the ComObjCreate approach you were working with before. Use the script you had before but with the attempt to get the element rather than set it.

Code: Select all

#SingleInstance force
#NoTrayIcon

wb := ComObjCreate("InternetExplorer.Application")
wb.Visible := true
wb.Toolbar := False
wb.Navigate("work_URL")

while wb.busy 
 
sleep, 100 

Sleep, 1000

workorder_number := wb.document.getElementById("claimNo").Value
msgbox %workorder_number%
If the page loads in IE, then it will, at a minimum, load and be visible. If the getElement fails, open IE (outside ahk), load your page, right click the element and choose 'inspect element.' That will bring up the DOM explorer and console. The DOM explorer will give you an idea of where your element exists in the page's hierarchy. This can be helpful, if say, the element is inside a frame, as the frame may need to be incorporated into your javascript.

Beyond looking at the DOM Explorer, you'll want to try a few different variables of your javascript in the console. I've spent a lot of time in the console tweaking a line of javascript, seeing what result it gave me, and then tweaking it again. For instance, sometime you have to use 'getAttribute' to get an attribute. I'm not saying this will work, but you could try (in the console):

document.getElementById("claimNo").getAttribute("value")

I'd like to say that I fully understand the DOM, but most of the time it's educated guessing. I generally find it helpful to get the larger stuff, and then work your way down, such as trying something along the lines of

document.getElementById("claimNo").innerHTML

It also might help to see if you can grab a parent node of the element you're trying to get.

Btw, what version of IE are you working with? These types of scripts will only work on version 9 and up.
What a great answer. I really appreciate it.

After reading your post, I looked more into the F12 of the page, and I took around a hundred 'educated' stabs in the dark and FINALLY got it to work. It was indeed inside of a frame, and I read around 100 different links because I really don't understand querying a webpage, but I finally got it to work. ... YES!

However, I am still running into an intermit problem now that it works. I used the following code to query the page;

Code: Select all

	wb := IEGet()
	try myIframe := wb.document.parentWindow.frames[1].document
	catch {
		myIframe := ComObj(9, ComObjQuery(wb.document.parentWindow.frames[1], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).document
		}
	myFrame := myIframe.parentWindow.frames[0].document
Then when I need to change the elements on the page, I use;

Code: Select all

myFrame.querySelectorAll("input")[27].value := ronumber
And this works, but, sometimes after the script runs once, sometimes after it runs 10 times, I get an error. All I have to do is close the script, close IE and reopen them both and it all works again, for a few script runs and then I get the same error again.
Error
Spoiler
Any idea what would cause this??

Thanks in advance
burque505
Posts: 1736
Joined: 22 Jan 2017, 19:37

Re: Help with controlling Internet Explorer

27 Jan 2017, 18:46

You might try "wb.Visible := 1" instead of "wb.Visible := true";
(maybe even (on the same line) if that doesn't work:)
wb.Visible := 1, wb.Activate
I have had this problem with Word. Using an integer, at least with Word, _does_ work.
This link may be of some help. https://gist.github.com/tmplinshi/cedaf22f1de666539886 (Windows_Data_Types_offline.ahk).
Or https://github.com/jNizM/AutoHotkey_MSDN_Types, a good one too.
Good luck!
enter8
Posts: 102
Joined: 05 May 2016, 16:48

Re: Help with controlling Internet Explorer

27 Jan 2017, 21:58

In my experience, issues with comobject javascript queries that sometimes work and sometimes fail are almost always a page loading/sleep issue.

It would be really beautiful if this worked all the time:

Code: Select all

while (wb.busy or wb.ReadyState != 4)
    sleep 100
but, for me, it fails on many pages, the query triggers before it loads and I end up with an error.

1. Simplest solution: Add a lot more sleep.

2. Slight more complicated. Add a loop to the try/catch:

Code: Select all

	wb := IEGet()
	Loop 200 ; sleeps for a total of 20 seconds
	{
		try ; if the query succeeds, it breaks the loop
			{
			myIframe := wb.document.parentWindow.frames[1].document
			break
			}
		catch ; if the query fails, it sleeps a bit and tries again 
			sleep 100
	}
	myIframe := ComObj(9, ComObjQuery(wb.document.parentWindow.frames[1], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).document
	myFrame := myIframe.parentWindow.frames[0].document
Now, I moved your catch query outside the loop, so this isn't finished, but I think you should understand what I'm trying to do. Btw, the query that your performing in your catch loop. Just to clarify, if the first query fails, you want it to try another?

3. Much more complicated solution:

I've worked on a try/catch subroutine that uses AHK_H and incorporates error logging, and incremental sleep (the more attempts it makes, the longer it sleeps). I've tested it quite a bit, and, so far, I haven't found any issues, but there's a chance there might be a bug. If you think you might want that, I'll post it.
Crashm87
Posts: 48
Joined: 25 Jul 2016, 13:12

Re: Help with controlling Internet Explorer

27 Jan 2017, 22:28

enter8 wrote:In my experience, issues with comobject javascript queries that sometimes work and sometimes fail are almost always a page loading/sleep issue.

It would be really beautiful if this worked all the time:

Code: Select all

while (wb.busy or wb.ReadyState != 4)
    sleep 100
but, for me, it fails on many pages, the query triggers before it loads and I end up with an error.

1. Simplest solution: Add a lot more sleep.

2. Slight more complicated. Add a loop to the try/catch:

Code: Select all

	wb := IEGet()
	Loop 200 ; sleeps for a total of 20 seconds
	{
		try ; if the query succeeds, it breaks the loop
			{
			myIframe := wb.document.parentWindow.frames[1].document
			break
			}
		catch ; if the query fails, it sleeps a bit and tries again 
			sleep 100
	}
	myIframe := ComObj(9, ComObjQuery(wb.document.parentWindow.frames[1], "{332C4427-26CB-11D0-B483-00C04FD90119}", "{332C4427-26CB-11D0-B483-00C04FD90119}"), 1).document
	myFrame := myIframe.parentWindow.frames[0].document
Now, I moved your catch query outside the loop, so this isn't finished, but I think you should understand what I'm trying to do. Btw, the query that your performing in your catch loop. Just to clarify, if the first query fails, you want it to try another?

3. Much more complicated solution:

I've worked on a try/catch subroutine that uses AHK_H and incorporates error logging, and incremental sleep (the more attempts it makes, the longer it sleeps). I've tested it quite a bit, and, so far, I haven't found any issues, but there's a chance there might be a bug. If you think you might want that, I'll post it.
I appreciate your help, again. Like I said, I don't fully understand the query, and that was what seemed to work for me after all my trial and errors. Now that you mention it, I do have that laid out rather silly.

I am going in implement your new page loading snippet and see if it cures the random errors. If it has issues, I'll maybe contact you for option number 3.


burque505 wrote:You might try "wb.Visible := 1" instead of "wb.Visible := true";
(maybe even (on the same line) if that doesn't work:)
wb.Visible := 1, wb.Activate
I have had this problem with Word. Using an integer, at least with Word, _does_ work.
This link may be of some help. https://gist.github.com/tmplinshi/cedaf22f1de666539886 (Windows_Data_Types_offline.ahk).
Or https://github.com/jNizM/AutoHotkey_MSDN_Types, a good one too.
Good luck!
Thanks for the links, I will give them a read. I am going to try changing my Visible lines as well.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Chunjee, macromint, peter_ahk and 322 guests