1

I recently needed to update an old FoxPro legacy application that uses Internet Explorer Automation to drive the content of a Web page by clicking some href links and entering data into a form and submitting.

This used to work just fine but checking on recent versions of Windows with IE 11 (windows 10) and also with IE 10 (Windows 7) I'm seeing that any click event calls on elements have no effect and they fail silently - no error, but also no click.

o = CREATEOBJECT('InternetExplorer.Application')
o.visible = .t.
o.Navigate('http://test.com/ControlBasics.wcsx')

wait window 'page loading...' timeout 1.5

* Target object has no id so navigate DOM to get object reference
oLinks = o.Document.getElementsByTagName('a')
oLink = oLinks.item(0)
oLink.Click()

* o.navigate(oLing.href) && works but not sufficient

o.document.getElementById('txtName').value = 'Rick'
oButton = o.document.getElementById('btnSubmit')
oButton.Click()

In the code above neither of the .click() event triggers have any effect. The assignment to the textbox however works fine, so the page is scripted.

Does anybody know what has changed or what might affect the behavior so that automating event code that previously worked no longer works?

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
  • What language is that, Cobol? It must be something to do with it, as [a simple VBScript test](https://gist.github.com/noserati/8a4bd489363f3228bcdb) works fine for me with IE11. – noseratio Jul 19 '15 at 05:19
  • 1
    It's FoxPro, but that brings up a good point. This used to work with the IE old style DOM (ie9 and older). In IE 10 they are using regular WC3 DOM style events and I wonder whether the problem is casing. One of FoxPro's shortcomings is that it will force COM calls to a specific case (I think it's lower case) and if the DOM event doesn't match it doesn't work. But oddly it does work with other properties etc. – Rick Strahl Jul 19 '15 at 16:48
  • Could that be related to the document you initially navigate (like document types, etc.)? Does noseratio's exact same script translated to FoxPro works? – Simon Mourier Jul 20 '15 at 10:16
  • No it doesn't work exactly that way. See the accepted answer for the actual problem. It has to do with optional parameters that are not supported by FoxPro and require a dummy parameter for no parameter functions on the DOM and JavaScript. There are a number of other ways to work around this, but the fake parameter is by far the easiest way to do it. – Rick Strahl Jul 22 '15 at 19:45

2 Answers2

5

Thanks to the comment of @Noseratio I was able to determine that the problem is specific to the FoxPro COM interface calling into the IE DOM. There are a number of quirks with FoxPro's COM implementation that involve casing and parameter counts. In this case the issue is the latter.

The way to fix the problem with FoxPro is to call the click method and pass any parameter - it doesn't matter what the value is you just have to pass one.

So this works:

oLinks = o.Document.getElementsByTagName('a')
oLink = oLinks.item(0)
oLink.Click(.F.)

and

o.document.getElementById('txtName').value = 'Rick'
oButton = o.document.getElementById('btnSubmit')
oButton.Click(.F.)

Notice the .F. parameter in both of those calls to the .Click() function.

I'm not quite sure what the issue is but my guess is that the default COM signature requires the arguments array and it has to be passed since FoxPro can't deal with optional parameters. By passing the value the COM signature is satisfied and the parameter is just ignored by the receiving function.

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
2

There's another possible way of automatic this: using JavaScript's eval. Here's a sample VBScript:

set ie = CreateObject("InternetExplorer.Application")
ie.visible = true
call ie.Navigate("http://goo.gl/gnhy85")
call Wscript.Sleep(5000)

set window = ie.Document.Script ' or ie.Document.parentWindow

' inject some script in case there's no <script> tags on the page,
' see http://stackoverflow.com/a/22372934/1768303
call window.setTimeout("(function() {})()", 0)
call Wscript.Sleep(100)

' automate
call window.eval(
    "(function() { document.getElementsByTagName('a').item(0).click(); })()")

Hopefully, FoxPro can handle the window.eval invocation, in which case you might not need any 3rd party code.

noseratio
  • 59,932
  • 34
  • 208
  • 486
  • 1
    Good idea. eval also doesn't work from FoxPro (for some reason that interface is not showing up at all), but execScript does and that does work. – Rick Strahl Jul 20 '15 at 08:40
  • 1
    @RickStrahl, they used to say [`execScript` is no longer supported](https://msdn.microsoft.com/en-us/library/ms536420(v=VS.85).aspx). Although, now given IE11 is the final version of IE, it might just stay there. I recall I did [some research on `eval`](http://stackoverflow.com/a/18349546/1768303) and it requires to be called via `IDispatchEx::Invoke` to work out-of-process. Most likely, FoxPro uses `IDispatch::Invoke`. – noseratio Jul 20 '15 at 09:02