在不可见的Web浏览器对象中模拟按键按下C#

3

我目前正在开发一个应用程序,需要使用 .net 3.5 中的 webbrowser 对象来导航网页并收集有关产品、价格等方面的数据。

问题在于该页面中有一些带有 ajax 建议脚本的字段,我无法简单地修改 innerText 属性,因为该脚本还会将代码保存在隐藏的输入字段中。

我需要一种方式来模拟在该字段中键入内容,然后发送“Enter”键,或者启动 ajax 脚本,然后发送“Enter”键,或者其他更好的方法来完成此操作。

3个回答

3

这似乎正是我所需要的,我将首先使用Beatles1692的想法进行快速测试(用于原型),然后再开始在最终版本中使用Watin。 - Artanis

2

要提交表单或运行脚本,可以这样做: 如果您知道脚本名称,则可以使用文档对象的InvokeScript:

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

第二个参数是一个对象数组,用于传递参数值。

如果您知道触发脚本的单击事件的元素名称,则可以执行以下操作:

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

1

使用标准的WebBrowser控件有几种方法可以实现此目的。

对于HTML:如果您想填写文本框然后单击提交,则甚至不需要按键。请执行以下操作:

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

这将比尝试为HTML发送按键要可靠得多。

**对于Flash:**如果网页上有需要点击的Flash元素,则无法使用此方法。在这种情况下,SendKeys是可靠的,但仅发送到活动应用程序,因此它无法在后台工作。您可以像这样发送窗口消息(示例将按字母“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)

您可以在pinvoke.net上在线查找PostMessage、GetClassName、GetWindow等的定义。请注意,WM_KEYUP使用c,但WM_KEYDOWN发送一个虚拟键(0)。KEYDOWN和KEYUP必须成对出现,否则键将无法注册,但如果您在发送时按住Control键,例如,KEYDOWN“p”,它将激活IE的打印功能。对于所有字母和数字,您可以发送0作为KEYDOWN,正确的字母作为KEYUP。退格似乎需要一个真正的KEYDOWN,而不是0,但在IE中,Control-Backspace似乎没有什么用处,因此如果c = vbBack,则KEYDOWN需要不同。

按键并不是非常准确,每500次中有1次会错过。但您可以将窗口最小化,没有问题,并且使用标准的WebBrowser控件。

另一个选择是使用AxWebBrowser。ActiveX控件似乎避免了Control-P问题,但它不像一个好的.Net控件那样容易操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接