IE编程

最近做项目需要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编程

网络编程,当然要用到Windows Socket(套接字)技术。Socket相关的操作由一系列API函数来完成,比如socket、bind、listen、connect、accept、send、sendto、recv、recvfrom等。调用这些API函数有一定的先后次序,有些函数的参数还比较复杂,对于开发者来说,不是很好用。于是,微软的MFC提供了两个类:CAsyncSocket和CSocket,极大地方便了Socket功能的使用。   CAsyncSocket类在较低层次上封装了Windows Socket API,并且通过内建一个(隐藏的)窗口,实现了适合Windows应用的异步机制(Windows Socket API默认情况下工作在阻塞模式,不方便直接在消息驱动的Windows程序上使用)。CSocket类从CAsyncSocket类派生,进一步简化了Socket功能的应用。不过很遗憾,正因为这两个类都内建了一个窗口,它们并不是线程安全的(thread-safe);如果要在多线程环境下应用Socket功能,建议自行封装Socket API函数。 基于TCP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到一个本地地址和端口号上(bind) 3、将套接字设为监听模式,准备接受客户请求(listen) 4、等待客户请求,请求到来时接受请求,建立链接,并返回 一个新的基于此次通信的套接字(accept) 5、用返回的套接字和客户端进行通信(send、recv) 6、返回,等待另一客户请求 7、关闭套接字 基于TCP的socket编程的客户端程序流程如下: 1、创建套接字 2、向服务器端发送请求(connect) 3、和服务器端进行通信(send、recv) 4、关闭套接字 基于UDP的socket编程的服务器端程序流程如下: 1、创建套接字 2、将套接字绑定到本地地址和端口号上(bind) 3、等待接收数据(recvfrom) 4、关闭套接字 基于UDP的socket编程的客户端程序流程如下: 1、创建套接字 2、和服务器端进行通信(sendto) 3、关闭套接字 异步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式;而同步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式。   阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,如果没有数据到达,将一直挂在recv()这个函数调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中,异步非阻塞套接字是用的最多的。平常所说的C/S(客户端/服务器)结构的软件就是异步非阻塞模式的。   对于这些概念,初学者的理解也许只能似是而非,我将用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制。目的是让初学者不仅对Socket异步非阻塞的概念有个非常透彻的理解,而且也给他们提供一个用Socket开发网络通信应用程序的快速入门方法。操作系统是Windows 98(或NT4.0),开发工具是Visual C++6.0。   MFC提供了一个异步类CAsyncSocket,它封装了异步、非阻塞Socket的基本功能,用它做常用的网络通信软件很方便。但它屏蔽了Socket的异步、非阻塞等概念,开发人员无需了解异步、非阻塞Socket的原理和工作机制。因此,建议初学者学习编网络通信程序时,暂且不要用MFC提供的类,而先用Winsock2 API,这样有助于对异步、非阻塞Socket编程机制的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值