Reputation: 1826
EDIT: part of this question is already answered elsewhere, but I feel this thread provides some more information and might be handy to know
Title pretty much says it all but here is some more information:
I have a function that uses the HTMLdocument of a global WebbBowser object to search for a specific object (i.e. a textbox). When the object is found, it will be given a value.
The function looks like this:
public static void Set_Elements_Input(string element_name, string value)
{
HtmlElementCollection hec = _wb.Document.GetElementsByTagName("input");
foreach (HtmlElement he in hec)
{
if (he.GetAttribute("name") == element_name)
{
he.SetAttribute("value", value);
}
}
}
Because of circumstances I am unable to debug in my programming environment. So I have to run the generated .exe to see if it works.. It doesn't.
My program crashes and the crashreport states that the crash was caused by an InvalidcastException.
With the help of the MessageBox.Show() method, I managed to find the point where everything goes bananas:
MessageBox.Show("I got here!");
HtmlElementCollection hec = _wb.Document.GetElementsByTagName("input");
MessageBox.Show("I didn't get here!");
This strikes me as odd, because I don't see how this could throw a InvalidCastException. I know foreach works with casts, but my program never seems to reach that code. That, and HTMLElementCollection is a collection of HTMLElements, so I don't see how that would case an InvalidCastException. Maybe when the collection is empty but I think there is a different Exception for that.
Than I thought, maybe it is because I am working with Threads and I have to use an invoke. But http://msdn.microsoft.com/en-us/library/system.windows.forms.htmlelementcollection.aspx says that HtmlElementCollections are Thread safe (or has that nothing to do with it?). That, and the function is static so I am not even sure if I can invoke.
So long story short, what is going on? And how can I fix it?
Upvotes: 1
Views: 1516
Reputation: 1826
Okay so I have looked at the answers and I managed to solve the problem. For some reason threading is the problem. And although HTMLElementsCollection is thread safe, the WebBrowser class isn't so I had to invoke it:
public static void Set_Elements_Input(string element_name, string value)
{
if (_wb.InvokeRequired)
{
_wb.Invoke(new Action(() => { Set_Elements_Input(element_name, value); }));
}
else
{
HtmlElementCollection hec = _wb.Document.GetElementsByTagName("input");
foreach (HtmlElement he in hec)
{
if (he.GetAttribute("name") == element_name)
{
he.SetAttribute("value", value);
}
}
}
}
But does anyone know why the original code would throw an InvalidCastException?
Upvotes: 0
Reputation: 1238
I think your foreach
causes this. foreach
had to cast to work on IEnumerable
. Using var in foreach
will take the type from IEnumerable<T>
if it is implemented by collection.
Upvotes: 0
Reputation: 107
i think you are trying to convert HTMLElement to collection. just a guess. you might aswell try to
HtmlElement hec = _wb.Document.GetElementsByTagName("input");
Upvotes: 0
Reputation: 2013
Maybe found the aswer here Threading and webbrowser control:
_wb.Invoke(new Action(() => {
HtmlElementCollection hec = _wb.Document.GetElementsByTagName("input");
foreach (HtmlElement he in hec)
{
if (he.GetAttribute("name") == element_name)
{
he.SetAttribute("value", value);
}
}
}
Upvotes: 1