2007年03月 存档

[原]C#和IE、Maxthon共享session cookie

2007年03月31日,星期六

最近写电子科大教务处的自动选科系统,遇到一个问题,如果先在 www.tad.uestc.edu.cn 登陆了,再用机器登陆并自动选课,那么IE/Maxthon就会提示:你的帐号已在别处登陆。也就是说一个帐号只能有一个 session 与服务器相连,那么可否实现我们的《自动选课机》与IE共享 session ,也就是说以同一个cookie和服务器对话呢?想了好久,有几个思路,一是用Win32API发送窗体消息,但是IE实在太复杂;二是拦截WinSock的包,这样实现起来也比较困难,第三就是用IE的接口来获取cookie信息了,那么这个接口是什么呢?显然 .NET 没有直接提供,那么就只有到 COM 里寻找了,对了,WSH/VBS里有一个着名的对象:InternetExplorer.Application,可以创建一个新的IE窗口,例如下面的vbs:

Set objIE =CreateObject("InternetExplorer.Application&quot ;)

objIE.Navigate("http://www.tad.uestc.edu.cn/&quot ;)

objIE.Visible=True

WScript.Sleep 1000 '等待页面载入

MsgBox objIE.Document.cookie

研究了下用C#完成同样的操作,真是麻烦啊,居然用到了反射。sign,大家可以对比下代码数量:

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Net;

using System.Reflection;

using System.Threading;

namespace WindowsApplication3

{

    public partial class Form1 : Form

    {

        WebClient wc;

        Type tp;

        Type tpDocument;

        object ie;

        object IEDocument;

        public Form1()

        {

            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)

        {

            tp = Type.GetTypeFromProgID("InternetExplorer.Application&quot ;) ;

            ie = Activator.CreateInstance(tp); //其实上面这么多代码就做了一件事情:CreateObject(),或者说JScript里面的new ActiveXObject()

            tp.InvokeMember("Navigate", BindingFlags.InvokeMethod, null, ie, new object[] { "http://www.tad.uestc.edu.cn" }); //相当于 ie.Navigate("http://www.tad.uestc.edu.cn&quot ;)

            tp.InvokeMember("Visible", BindingFlags.SetProperty, null, ie, new object[] { true }); //相当于 ie.Visible=ture

            Thread.Sleep(1000); //等待页面载入,否则会出现 HRESULT 错误

            IEDocument = tp.InvokeMember("Document", BindingFlags.GetProperty, null, ie, null); //获得 ie.Document 对象,是一个 mshtml.HtmlDocument COM对象,也就是JScript里的DOM,例如 window.document

            tpDocument = IEDocument.GetType();

        }

        private void button1_Click(object sender, EventArgs e)

        {

            textBox1.Text=tpDocument.InvokeMember("cookie", BindingFlags.GetProperty, null, IEDocument, null).ToString(); //相当于 ie.Document.cookie。

            //从上面的代码可以看出,用C#操作COM是相当麻烦的。VBS几句话,C#就会写大段的代码,很多是重复的,都是为了万恶的strong type。还是脚本好啊,免去了很多后台转换代码,呵呵。

            //写COM Interop最麻烦的就是异常处理了,很多 HRESULT 不知道怎么办,郁闷。微软的兼容性真糟糕!

        }

        private void Form1_Leave(object sender, EventArgs e)

        {

        }

    }

}

[内有附件]