views:

2652

answers:

4

I'm currently working in an application that has to navigate a webpage and recollect data about products, prices, ... with webbrowser object in .net 3.5.

The problem is that the page has some fields with a suggest script in ajax, and I can't simply modify the innerText property because the script also saves codes in a hidden input field.

I need a way to simulate the typing in that field and then send the "Enter" key, or launch the ajax script and then send the "Enter" key, or any better ways to do this.

+1  A: 

Use Watin

Then you can use this solution.

Mischa Kroon
That appears to be just what I needed, I'll make a quick test with Beatles1692 idea first (for the prototype) and then I'll start using Watin for the final version.
Artanis
+1  A: 

To submit a form or run a script you can do this: If you know the script name you can use InvoekScript of Document object:

myWebBrowser.Document.InvokeScript("script-name",null);

the second argument is an array of objects to pass parameters values.

if you know the name of an element that it's click event fires the script you can do this:

HtmlElement element=myWebBrower.Document.GetElementById("element-name")[0];
element.InvokeMember("click");
Beatles1692
A: 

Some AJAX elements do not react to element.InvokeMember("click").

A simple sendkeys script might work for your project, but the most reliable way is to hook the web browser control (very tricky, but doable). Or you purchase a ready-made component such as iMacros: http://www.iopus.com/iMacros/component.htm

RegExGuru
+1  A: 

There are a few ways to do this with the standard WebBrowser control.

For HTML: If you want to fillout a textbox and then click submit then don't even bother with a keypress. Do this:

webbrowser1.Navigate("javascript:function%20E(){f0=document.forms[0];f0['login'].value='foo';}E()")
webbrowser1.Navigate("javascript:document.forms[0].submit()")

This will be much more reliable then trying to send keypresses for HTML.

For Flash:If there's a flash element on the webpage that needs clicking then it won't work. In that case SendKeys is reliable but only sends to the active application so it won't work in the background. You can send windows messages like this (example will press the letter "f"):

Dim c as char = "f"c
Dim classname As New System.Text.StringBuilder(100)
Dim ExplorerHandle As IntPtr = webbrowser1.Handle
GetClassNameA(ExplorerHandle, classname, classname.Capacity)
Do While classname.ToString <> "Internet Explorer_Server"
    ExplorerHandle = GetWindow(GetExplorerHandle, GetWindow_Cmd.GW_CHILD)
    GetClassNameA(ExplorerHandle, classname, classname.Capacity)
Loop

PostMessageA(ExplorerHandle, WM_Constants.WM_KEYDOWN, IntPtr.Zero, IntPtr.Zero)
PostMessageA(ExplorerHandle, WM_Constants.WM_KEYUP, CType(VkKeyScanA(CType(Asc(c), Byte)), IntPtr), IntPtr.Zero)

You can find the definitions for PostMessage, GetClassName, GetWindow, etc, online at pinvoke.net. Notice that the WM_KEYUP uses c but the WM_KEYDOWN sends a dummy key (0). KEYDOWN and KEYUP have to go in pairs or else the key won't be registered, but if you hold down Control while sending, for example, KEYDOWN "p", it will activate IE's print function. For all the letters and digits you can send 0 for KEYDOWN and the correct letter for KEYUP. Backspace seems to need a real KEYDOWN, not 0, but Control-Backspace doesn't seem to do much in IE so if c = vbBack, KEYDOWN needs to be different.

The keypresses aren't very accurate, either, and 1 time in about 500 it misses. But you can do it with the window minimized, no problem, and a standard WebBrowser control.

Another option is to use AxWebBrowser. The ActiveX control seems to avoid the Control-P problem but it's not as easy to manipluate because it isn't a nice .Net control.

Eyal