最近做项目需要IE编程,得到一点经验
webbrowers 控件
打开网页,
Object url="http://local/index2.asp";
axWebBrowser1.Navigate2(ref url);
其中Navigate2方法比Navigate方法多了一些功能,比如打开文件夹(没试过)
NavigateComplete事件在DocumentComplete事件之前执行
已模似网页操作为例子
如果是做winform程序
比如你要进行打开网页,填写数据,点击提交等操作
下面代码
int cmdNum
private void button1_Click(object sender, System.EventArgs e)
{
Object url="http://local/index2.asp";
axWebBrowser1.Navigate2(ref url);
}
private void Form1_Load(object sender, System.EventArgs e)
{
//命令集合
al=new ArrayList();
al.Add(new command(1,"staff_name_en","InputText","zuoqs"));
al.Add(new command(2,"password","InputText","js020508"));
al.Add(new command(3,"submit","submit","{enter}"));
}
private void axWebBrowser1_DocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)
{
timer1.Enabled=false;//计时器暂停
axWebBrowser1.Focus();
mshtml.HTMLDocumentClass doc=(mshtml.HTMLDocumentClass)axWebBrowser1.Document;
if(doc.location.href.IndexOf("mis/index2.asp")>-1)
{
if(doc.body.innerText.IndexOf("你不是合法用户")>-1||doc.body.innerText.IndexOf("你的口令输入错误")>-1)
{
label1.Text="登陆失败";
timer1.Enabled=false;
return;
}
}
timer1.Enabled=true;//处理完逻辑后开启
}
private void timer1_Tick(object sender, System.EventArgs e)
{
timer1.Enabled=false;//计时器暂停
axWebBrowser1.Focus();//控件焦点获取
if(cmdNum==al.Count)
{
timer1.Enabled=false;//如果命令执行完后计时器暂停
}
else
{
mshtml.HTMLDocumentClass doc=(mshtml.HTMLDocumentClass)axWebBrowser1.Document;
command cmd = (command)al[cmdNum];
switch (cmd.ElementType)
{
case "InputText":
{
mshtml.HTMLInputTextElement element = (mshtml.HTMLInputTextElement)doc.all.item(cmd.ElementId,0);
element.focus();//文本框获取焦点
SendKeys.Send(cmd.CommandString);//模似键盘打字
break;
}
case "submit":
{
mshtml.HTMLInputButtonElement element = (mshtml.HTMLInputButtonElement)doc.all.item(cmd.ElementId,0);
element.focus();
SendKeys.Send(cmd.CommandString);//提交表单后,计时器关闭,等页面加载完后开启
cmdNum++;
timer1.Enabled=false;
return;
}
case "button":
{
mshtml.HTMLInputButtonElement element = (mshtml.HTMLInputButtonElement)doc.all.item(cmd.ElementId,0);
element.focus();
SendKeys.Send(cmd.CommandString);
break;
}
cmdNum++;
timer1.Enabled=true; //计时器开启
}
以上是基本方法,但会有一些问题
执行js脚本
(mshtml.HTMLDocumentClass)axWebBrowser1.Document.parentWindow.execScript("alert()","javascript")
如果希望网页不会有alert,confirm,脚本报错等,可以使用下面的js脚本
window.alert=function(){}; window.confirm=function(){return true}; window.onerror=function(){return true};
屏蔽弹屏
private void axWebBrowser1_NewWindow3(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow3Event e)
{
e.cancel=true;
}
弹屏在另一个webbrowers打开
private void axWebBrowser1_NewWindow2(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
e.ppDisp=axWebBrowser2.Application;
}
访问iframe
mshtml.IHTMLWindow2 farme = (mshtml.IHTMLWindow2)doc.frames.item(ref main);
这里很关键的地方是用IHTMLWindow2而不是用mshtml.HTMLIFrame
如果你是做类库,那你不能有可视的界面,那你也不能模似键盘的操作了,你需要用SHDocVw.dll,这个文件在system32里面,提供和webbrowers一样的功能
public void openIE2()
{
Thread t=new Thread(new ThreadStart(threadOpenIE));
t.Name="changeorder";
t.Start(); //用多线程,这样可以并行打开多个网页
}
public void threadOpenIE()
{
object objFlags=0; //0无页面,有缓存 1有页面,无缓存
object objTargetFrameName="";
object objPostData="";
object objHeaders="User-Agent: Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.0)"; //可不写
SHDocVw.InternetExplorerClass a;
try
{
a=new SHDocVw.InternetExplorerClass();
}
catch(Exception e)
{
a=null;
throw e;
System.Threading.Thread.CurrentThread.Abort();
}
a.Navigate("http://localhost/action/HTMLPage1.asp",ref objFlags,ref objTargetFrameName,ref objPostData,ref objHeaders); //如果objFlags=0是不会弹出页面的,但可以把网页的dom对象保存在内存中,如果objFlags=1就会弹出ie,网页的内容也不会在内存中保存了
while (a.Busy);//不断访问页面直到页面加载结束.这里指服务器的响应,而不是js代码,也就是说再复杂的js代码也不会影响a.busy的状态
mshtml.HTMLDocumentClass doc=(mshtml.HTMLDocumentClass)a.Document;//如果objFlags=1就会报错
mshtml.HTMLSelectElementClass selectelement = (mshtml.HTMLSelectElementClass)doc.all.item("reser_status",0);
selectelement.selectedIndex=2;//如果不知道index可以用selectelement.value="**";
object aaa=null;
selectelement.FireEvent("onchange",ref aaa);//因为无法模似键盘,所以页面上任何onchange类型js脚本无法运行,所以用FireEvent来激活onchange事件.
mshtml.HTMLInputTextElement textelement = (mshtml.HTMLInputTextElement)doc.all.item("price_admin",0);
textelement.value=textelement.value;
mshtml.HTMLInputButtonElement element = (mshtml.HTMLInputButtonElement)doc.all.item("su",0);
//这里如果网页很大,可以不会一次取到,要取多次
//for (int i = 0; i < times; i++)
// {
// if (Element == null)
// Element = doc.all.item(ElementName, index);
// else
// break;
// }
element.click();
while (a.Busy)
{
System.Threading.Thread.Sleep(500);//这样做可以减少访问页面的次数
}
while (a.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
System.Threading.Thread.Sleep(500);//a. busy等于fase的时候,页面也可能没有加载完,一定要有这步
}
doc=(mshtml.HTMLDocumentClass)a.Document;
string html=doc.body.innerHTML;
a.Quit();
System.Threading.Thread.CurrentThread.Abort();
}
也许有个会问为什么不用DocumentComplete事件,因为这个事件无非是又开一个线程进行监听,作为类库程序,主线程很容易执行完,释放资源,DocumentComplete执行完后将无法找到原来调用它的线程,如果一定要用的话可以这样用.
a.DocumentComplete+=new SHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(a_DocumentComplete);
System.Threading.Thread.Sleep(3000);// 主线程等待为了使a_DocumentComplete可以执行,但做为类库项目不建议这样做,我们可以发现一般需要监听其它资源的事件都是新开线程,当事件激活后,回调方法时,主线程应确保还在内存中存在.
多线程使用SHDocVw.dll会丧失很多功能,比如doucment里面的parentwindow,iframe,script等属性可以访问不到.
调用com组件有一个不好就是很多错误都是未指定错误,所以你不知道是因为什么出的错.看错误可以看comException类的hresult属性,com组件报的错都是个数字,可惜的是,很多数字微软都说成未指定错误.
关闭窗口方法
browers.quit();
用javascript方法
doc.parentWindow.opener=null;
doc.parentWindow.open("","_top","",false);
doc.parentWindow.close();
对于很多页面元素的操作,没有什么资料,完全靠试,比如遍历某个select的option
mshtml.HTMLSelectElementClass dd=(mshtml.HTMLSelectElementClass)doc.all.item("ddd",0);
mshtml.IHTMLElementCollection aaa= (mshtml.IHTMLElementCollection)dd.children;
//这里试了半天才试出来,HTMLSelectElementClass.options HTMLSelectElementClass.childnodes 都没有办法转化为IHTMLElementCollection
如果是option集合,不要想利用IHTMLElementCollection.item(name,index)的方法遍历,因为option是没有name的,如果试图采用IHTMLElementCollection.item(null,index)不管你index是几,返回结果都是第一个元素.
要用foreach
foreach(mshtml.HTMLOptionElementClass option in aaa)
{
string sd= option.value+option.text;
}
不过好像并不是所有的集合都可以foreach,不过在这里是可以用的
new一个SHDocVw.InternetExplorerClass();系统里面就会多一个iexplorer进程,记住一定要quit掉,用单例模式性能应该高点.
相关技术文章可以搜 如何对webbrowser和IE编程
777

被折叠的 条评论
为什么被折叠?



