pu369com

重拾Csharp操控IE浏览器(一)死而不僵的IE

可以直接从第5步开始看:-)

需求:

   落后的企业规定必须使用IE,用chrome无法正常显示和上传,还装了一些ACTIVEX之类插件。于是想将繁琐工作步骤自动执行。

1、弯路:

  原想参考https://golangnote.com/topic/230.html 用golang Selenium WebDriver ,从国内镜像下载了DriverServer.exe,好不容易编译成功了,又提示要java;又好不容易重新安装了jdk11,又提示IE Protection Mode之类,把IE启用保护模式选项关掉,又提示一些错误。懒得弄了。

2、具备写代码条件:

  打开VS2017(社区版),又遇到许可证过期,更新许可证无效。网上找到解决方案:在D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE下运行DDConfigCA.exe,然后在网页上先登录hotmail.com,再次更新许可证,终于将VS2017恢复正常了。

3、操控IE还是C#最在行: 

  其实最主要就是用SHDocVw.InternetExplorer控制IE,用 mshtml.HTMLDocument获取html元素,然后进行导航、输入、点击按钮。

4、进入正题:

  VS2017新建解决方案(我是打开以前的方案),主要是先建一个winform应用(.net framework4.5.1),首先要添加引用,记得是从COM中添加了microsoft internet controls和从程序集扩展里添加了Microsoft.mshtml,并且设 嵌入互操作类型为true,参考我之前的文章:https://www.cnblogs.com/pu369/p/9068972.html  剩下的就是放置一些按钮或menuStrip,添加click事件。

5、一些实例代码

5.1 判断VPN是否连接了(其实就是判断进程中是否有gwtrayclient)

  Process[] app = Process.GetProcessesByName("XXtrayclient");

然后判断 app.Length > 0,说明有这个进程了。

5.2连接VPN(其实就是模仿登录网页,登录成功后电脑会调起XXtrayclient;其中用IE.Busy循环等待IE加载完成) 

        private void 公司ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SHDocVw.InternetExplorer IE = new SHDocVw.InternetExplorer();
            object Empty = 0;
            object URL1 = "https://vpn.XXX.com.cn";
            object URL2 = "https://wssvn.XXX.com.cn";
            IE.Visible = true;
            IE.Navigate2(ref URL1, ref Empty, ref Empty, ref Empty, ref Empty);
            System.Threading.Thread.Sleep(2000);
            IE.Navigate2(ref URL2, ref Empty, ref Empty, ref Empty, ref Empty);
            do
            {
                System.Threading.Thread.Sleep(500);
            } while (IE.Busy);
            mshtml.HTMLDocument doc_oa = IE.Document;
            var inputs = doc_oa.getElementsByTagName("input");  //获取用户名输入框    
              //input没name属性,可以用className判断
            foreach (mshtml.HTMLInputElementClass input in inputs)
            {
                var a = input.className;
                var b = Convert.ToString(input.getAttribute("className"));
                if (input.className == "login")
                {
                    input.click();
                }
            }

        }

 5.3输入用户名密码登录

        private void 公司ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                this.WindowState = FormWindowState.Minimized;
                SHDocVw.InternetExplorer IE = new SHDocVw.InternetExplorer();
                object Empty = 0;
                object URL = "http://www.xxx.com/login.jsp";
                IE.Visible = true;
                IE.Navigate2(ref URL, ref Empty, ref Empty, ref Empty, ref Empty);
                do
                {
                    System.Threading.Thread.Sleep(500);
                } while (IE.Busy);
                var doc_oa = (mshtml.HTMLDocument)IE.Document;
                var userid_oa = (mshtml.HTMLInputElementClass)doc_oa.getElementById("loginid");  //获取用户名输入框                 
                var userpwd_oa = (mshtml.HTMLInputElementClass)doc_oa.getElementById("userpassword");//#获取密码输入框
                userid_oa.value = "admin"; //#输入用户名  
                userpwd_oa.value = "1234";//输入密码  
                var btSubmit_oa = (mshtml.HTMLInputElementClass)doc_oa.getElementById("login");//获取登录按钮  
                btSubmit_oa.click();//点击         
                //关闭登录提示
                System.Threading.Thread.Sleep(2000);
                var oa_ButtonCancel_0 = IE.Document.getElementById("_ButtonCancel_0");
                oa_ButtonCancel_0.click();
            }
            catch (Exception e1)
            {
               // MessageBox.Show("error IE" + e1.Message);
            }

        }

5.4将程序本身最小化

 this.WindowState = FormWindowState.Minimized;

5.5打开记事本

  System.Diagnostics.Process.Start("notepad.exe");

5.6为了方便操作已经打开的IE页面,自定义了一个iehastitle函数,用于根据部分标题查找打开的IE窗口

        public SHDocVw.InternetExplorer iehastitle(string s)
        {
            //查找标题包括s的IE             
            SHDocVw.ShellWindows windows = new SHDocVw.ShellWindows();
            var title = "";
            for (int i = 0; i < windows.Count; i++)
            {
                SHDocVw.InternetExplorer IE = windows.Item(i) as SHDocVw.InternetExplorer;
                if (IE != null)
                {
                    title = IE.LocationName;
                    if (title.Contains(s))
                    {
                        return IE;
                    }
                }                
            }
            return null;
        }

5.7遇到的难点之一是frameset套frameset(其中外层frameset中有1个frame,内层frameset中有4个frame;frame中还有iframe)参考代码: 

//网页是frameset套frameset,其中:外层frameset中有1个frame,
//内层frameset中有4个frame(name分别是menu、list、file、rightbar);
//frame[2](name为list)中还有iframe
//首先找到办公自动化页面
var IE = iehastitle("办公自动化");
mshtml.HTMLDocument IE_doc = IE.Document;
//当前网页中frames总数5个(即上面说的外层的1个和内层的4个共5frame,后面我称之为第0个至第4个frame,没有frameset什么事)
int frame_num = IE_doc.frames.length;
//item(0)在外层frameset中,称之为第0个frame,类型是HTMLWindow2          
//最主要需获取的是frame[2](name为list),其中还有iframe
//frame2的window
mshtml.HTMLWindow2 frame2_win = IE_doc.frames.item(2) as mshtml.HTMLWindow2;
//frame2的document
mshtml.HTMLDocument frame2_doc = frame2_win.document as mshtml.HTMLDocument;
//frame2中的iframe的window
var frame2_iframe = frame2_doc.frames.item(0) as mshtml.HTMLWindow2;
//iframe的document
var iframe_doc = frame2_iframe.document as mshtml.HTMLDocument;
var iframe_htmlstr = iframe_doc.body.innerHTML;
var links = iframe_doc.getElementsByTagName("a");

可简化成类似下面的一句:

mshtml.HTMLDocument iframe_doc = (((IE.Document.frames.item(2) as mshtml.HTMLWindow2).document as mshtml.HTMLDocument).frames.item(0) as mshtml.HTMLWindow2).document as mshtml.HTMLDocument;

 

5.8难点之二是confirm对话框和alert对话框的关闭,在webBrowser1_Navigated或webBrowser1_DocumentCompleted的时候用doc.parentWindow.execScript执行javascript脚本;还可参考https://www.cnblogs.com/qqhfeng/p/4194938.html,禁止脚本错误。

//注意:一定要放到你的代码执行前面,这样有弹出框的时候才会自动点击,如果把这段代码放到你点击按钮之后,点击按钮弹出的提示框是自动点击不了的
doc.parentWindow.execScript("window.openr=null;function confirm(str){return true;} ", "javascript"); //弹出确认
doc.parentWindow.execScript("window.openr=null;function alert(str){return true;} ", "javaScript");//弹出提示

5.9启动线程(其中gethrp可以是自定义的  private static void gethrp()函数)

    Thread thread = new Thread(new ThreadStart(gethrp));
            //启动线程
            thread.Start();   

5.10存盘

      //写盘 
            if (info != "") { 
                 using (StreamWriter sw = new StreamWriter(@"D:\hrp.txt", true)) { sw.WriteLine(info); }
            } 

5.11读取文档

 using (StreamReader sr = new StreamReader(@"E:\memo.txt")) { this.textBox1.Text = sr.ReadToEnd(); }

5.12将form显示在最上层

  this.TopMost = true;

5.13执行adb命令打开手机电源

 private void adbToolStripMenuItem_Click(object sender, EventArgs e)
        {
            String exe = Application.StartupPath + "\\adb\\adb.exe";         
            Process p = new Process();
            p.StartInfo.FileName = exe;           //设定程序名              
            p.StartInfo.UseShellExecute = false;        //关闭Shell的使用   
            p.StartInfo.RedirectStandardInput = true;   //重定向标准输入   
            p.StartInfo.RedirectStandardOutput = true//重定向标准输出   
            p.StartInfo.RedirectStandardError = true;   //重定向错误输出   
            p.StartInfo.CreateNoWindow = true;          //设置不显示窗口     
            p.StartInfo.Arguments = "devices";    //设定程式执行參數              
            p.Start();
            this.label1.Text = p.StandardOutput.ReadToEnd();
            p.StartInfo.Arguments = "shell input keyevent  26";    //设定程式执行參數           
            p.Start();
            if (p != null)
            {
                p.Close();
            }

        }

5.14下载网络图片

//DownloadImage(url, @"d:\a.jpg");
public void DownloadImage(string url, string path)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.ServicePoint.Expect100Continue = false;
            req.Method = "GET";
            req.KeepAlive = true;
            req.ContentType = "image/*";
            HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
            System.IO.Stream stream = null;
            try
            {
                // 以字符流的方式读取HTTP响应
                stream = rsp.GetResponseStream();
                Image.FromStream(stream).Save(path);
            }
            finally
            {
                // 释放资源
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }

5.15根据url找已经存在的IE

        public SHDocVw.InternetExplorer iehasurl(string s)
        {
            //查找url包括s的IE             
            SHDocVw.ShellWindows windows = new SHDocVw.ShellWindows();
            var url = "";
            for (int i = 0; i < windows.Count; i++)
            {
                SHDocVw.InternetExplorer IE = windows.Item(i) as SHDocVw.InternetExplorer;
                if (IE != null)
                {
                    url = IE.LocationURL;
                    if (url.Contains(s))
                    {
                        return IE;
                    }
                }
            }
            return null;
        }

 

posted on 2020-02-22 10:31  pu369com  阅读(775)  评论(0编辑  收藏  举报

导航