前一阵子公司开始用OA系统,想研究自动化审批,不要自己点来点去了。OA的界面做的确实不怎么样,一条一条地批文件实在有点不爽。
于是开始研究写程序在网页上自动审批。
先用findwindow和findwindowEx,结果SPY++不能发现网页上的控件,不知道微软怎么连自己的东西都找不着。换方法!!
再用微软的webbrowser控件和Vb.net操练一下,本来以为是手到擒来,不就是找控件填写数值和按钮点击吗?
第一个问题是一碰到了网页中有FRAME,DOM中的findelementbyId就失效了,要切换到相应的FRAME中才能找到。
还要监视FRAME里的AJAX加载完毕,这OA做得太复杂了,用F12一看HTML里面套得象麻花一样。
下面碰到要点击链接,一点之下发现会有弹出网页,webbrowser立刻不管用了,弹出的窗体不在webbrowser中,立刻报告超时,要求重新登录。而且弹出窗体的url是原网页中用js合成的,由于有中文还用了uriencode。在WINFORM中放置第二个webbrowser的想法来用新URL展示网页的愿望就破灭了。
遍查百度,想截获webbrowser控件的http请求来找到新生成的url,最后以失败告终。
无意中发现有人提到了webdriver可以进行web应用的测试,于是就下载了DLL来用。webdriver IDE插件只支持在firefox中录制脚本,于是在firefox中打开公司的OA,结果发现OA的代码太老了(在IE中也要用兼容视图才行),有的网页在新版的firefox中根本显示不全,于是只好一句一句地到网上学代码。但是当碰到弹出网页时也搞不定了,而且每次运行都有一个黑控制台窗口。又在网上见到了watir webdriver,也试了一下,还要学RUBY,幸好网上有位叫乙醇的大侠有整套的教程,安装和学习都比较方便,但乙醇告知,模态窗体好像用WWD搞不定。于是又试按键精灵,这个软件是可以录制的,看了教学录像,然后动手在WQM自带浏览器中录制,结果碰到弹出对话框时,一个对话框变成了四张网页,只好向按键精灵的网站提交了BUG。
再试AUTOIT,一句一句的到网上抄代码苦干两天,终于搞定。这软件虽然不能录制,但一定要下载它的汉化版,可以自动添加调试的对话框和CONSOLE输出调试信息,还可以编译成EXE,也能支持数据库,还可以被Vb、RUBY等程序调用,一个字爽。上代码(半个月的努力结果啊。):
#include<IE.au3>
#AutoIt3Wrapper_run_debug_mode=Y
$oIE = _IECreate('http://111.11.1.11:1111/defaultroot/login.jsp');进入登录界面
$oForm = _IEFormGetCollection ($oIE, 0)
;MsgBox(0, "Form Info", $oForm.name)
_IEFormSubmit ($oForm);因为用户名和密码已经被网页记住,所以直接提交
$oFrame=_IEFrameGetObjByName($oIE,"MainDesktop" );AJAX方式加载新网页,处理其中的FRAME.
_IELoadWait($oFrame)
Sleep(3000)
$oLinks = _IELinkGetCollection($oFrame);获取FRAME中的全部链接。
For $oLink In $oLinks
$sLinkText = _IEPropertyGet($oLink, "innerText")
If StringInStr($sLinkText, "待办文件") Then
_IELinkClickByText($oFrame, $oLink.innertext));找到FRAME中的含有"待办文件"内容的链接并点击。
ExitLoop
EndIf
Next
;点击待批文件
$oFrame0=_IEFrameGetObjByName($oIE,"mainFrame" );AJAX在网页的另一FRAME中加载待批文件
列表
_IELoadWait($oFrame0);等待FRAME回迁完成
Sleep(3000)
$oFrame=_IEGetObjByName($oFrame0,"iframe1" );frame中还套着FRAME,再找一下吧。
;MsgBox(0, "iframe1 Info", $oFrame.name)
$oLinks = _IELinkGetCollection($oFrame)
For $oLink In $oLinks
$sLinkText = _IEPropertyGet($oLink, "innerText");找到FRAME中的所有链接
If StringInStr($sLinkText, "等待您的办理") Then
_IELinkClickByText($oFrame, $oLink.innertext);找到FRAME中的有"等待您的办理"的第一个链接并点击
ExitLoop
EndIf
Next
Sleep(3000)
$sTitle=WinGetTitle("[active]");等待新网页弹出
$oIE1 = _IEAttach ($sTitle,"embedded")
Local $oInputs = _IETagNameGetCollection($oIE1, "textarea");找到输入框,写“同意”
$oInput = $oInputs(0)
$oInput.value="同意"
$oSpans = _IETagNameGetCollection($oIE1, "span")
For $oSpan In $oSpans
If StringInStr($oSpan.innertext, "发送") Then;找到发送按钮,点击,这个按钮是用SPAN写的,真邪门。
_IEAction($oSpan, "click")
EndIf
Next
;点击确认窗口
Sleep(3000)
$sTitle=WinGetTitle("[active]")
$oIE2 = _IEAttach ($sTitle,"embedded")
Local $oInputs = _IETagNameGetCollection($oIE2, "input")
For $oInput In $oInputs
If StringInStr($oInput.value, "发送") Then;又弹出一个网页对话框,还要点一下发送,这不是垃圾设计吗?
_IEAction($oSpan, "click")
EndIf
Next
;sleep(1000)
;处理模态窗体
WinWaitActive("来自网页的消息")
;WinWait("来自网页的消息")
ControlClick("来自网页的消息", "", "[CLASS:Button; Instance:1;]");又要处理一个对话框,垃圾设计啊。
_IEQuit ($oIE)
后面还要再研究一下如何在VB.NET中用这个东西。再研究一下RUBY,PYTHON看起来也挺顺眼,有空也要学一下。