最近写电子科大教务处的自动选科系统,遇到一个问题,如果先在 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" ![]()
objIE.Navigate("http://www.tad.uestc.edu.cn/" ![]()
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"
;
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" ![]()
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)
{
}
}
}
[内有附件]