Ok - first things first: I have actually resolved this issue, and I will outline the problem as well as my solution. My question is really to see whether anybody can explain what was happening and why the solution I eventually implemented does work when the original code doesn't.
We are integrating some third party software to ours through a REST API. During the initial Authentication step, their software presents the user with a "Login" page through which they can then retrieve an authentication code that is then used for the duration of the session. To improve the user experience we are loading this "Login" page into a WebBrowser control, we then use the DOM to find the INPUT elements that the user needs to enter data into, enter data into those automatically and Submit the form. Easy, right?
Here are a few sample lines of the original code, where wbLogin is the WebBrowser control:
To get the INPUT element into which the user should enter their e-mail address
oEmail = wbLogin.Document.getElementsByName("email").item(0)
or
oEmail = wbLogin.Document.getElementById("LoginEmail")
To get the Form that needs to be Submitted:
If Not wbLogin.Document Is Nothing Then
If Not wbLogin.Document.Forms Is Nothing Then
If wbLogin.Document.Forms.length > 0 Then
oForm = wbLogin.Document.Forms.item(0)
End If
End If
End If
To submit the actual Form
oForm.Submit()
But here is where it got weird. This all worked perfectly the first time I loaded the dialog and I did all this. But the second time I would load the same dialog with the same Page I would get NotSupportedError exceptions "System.NotSupportedException: Exception from HRESULT: 0x800A01B6" for example
And this is where it got weird. As I was stepping through the code and I found that
wbLogin.Document.getElementsByName("email")
was failing, I found that
wbLogin.Document.getelementsbyname("email")
succeeded. So I went down a rabbit hole, where I started writing code trying the first variation first, and the second variation next. But I soon found that this would fail on a THIRD iteration, and then
wbLogin.Document.GetElementsByName("email")
would succeed... or
wbLogin.Document.GETELEMENTSBYNAME("email")
Similarly, oForm.Submit() would work once, then oForm.submit(), then oForm.SUBMIT(), but every variation would work ONLY once. Restarting the application would "clean the slate", of course, but this happened during each session.
And it got even worse. The more I coded for exceptions like these, the more the code would simply start failing somewhere else. And with the craziest errors to boot. At some point I would get these methods returning DBNulls, or Booleans. And yet I persisted in coding for more and more exceptions. Try/Catch blocks everywhere, but everytime I tried ONE thing, something else would fall over or something else would return nonsense. I was tearing my hair out. I tried coding my own walk through the DOM trying to find the elements by brute force, but even THAT caused errors on subsequent access. My original code of a couple of handfuls of lines bloated to over 500 lines and I was still nowhere near a solution.
Thankfully I eventually found a solution that works every time
For example, to get the aforementioned INPUT field, I now do this:
Dim oDocType As System.Type = wbLogin.Document.GetType
Try
oEmail = oDocType.InvokeMember("getElementById", Reflection.BindingFlags.Default + Reflection.BindingFlags.InvokeMethod, Nothing, wbLogin.Document, {"LoginEmail"})
Catch
End Try
To submit the form:
oForm.GetType().InvokeMember("submit", Reflection.BindingFlags.Default + Reflection.BindingFlags.InvokeMethod, Nothing, oForm, {})
So my questions are:
User contributions licensed under CC BY-SA 3.0