MFC模拟登陆、操作路由器

之所以要做这个,因为有个客户要求咱们不能手工用浏览器登陆路由器web界面去操作,这样会泄漏产品的原理等信息。 没办法,只能做咯,尽管有点奇葩这个做法。

路由器选用的是磊科的NR238, 初始账号密码在路由器背面有写着,我以修改其中的WAN口静态IP为例讲述:

1、首先新建一个MFC对话框工程,然后在资源视图里找到“工具箱”, 右击任意一个控件,选择“选择项”。


弹出对话框中,按照下图进行添加web控件


此时可以在工具箱里找到Microsoft Web Browser,拖进到对话框里。这样子对话框便能如浏览器一样的访问网站。


2、关键部分代码

void CsetRouteDlg::DoDataExchange(CDataExchange* pDX)
{
	CDHtmlDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EXPLORER1, myExPlorer);
	//::ShowWindow(myExPlorer.GetSafeHwnd(), SW_HIDE);
	CComVariant vtUrl;//用以存储打开网址
	vtUrl = (L"http://guest:guest@192.168.12.1"); //+ editIP;
	CComVariant vtEmpty;
	myExPlorer.Navigate2(&vtUrl, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty);
}
以上的myExPlorer为web控件变量, Navigate2方法为连接地址方法,其中http://guest:guest@192.168.12.1的格式为:  帐号:密码@IP地址  ,注意此处DoDataExchange是对话框加载时会被马上执行,也就是执行软件马上去连接网址, 所以相应的网址内容请读者自行修改,否则不能正常打开软件。在调试阶段,可以让web控件可视,当调试完毕,可以在此加入隐藏控件语句:
::ShowWindow(myExPlorer.GetSafeHwnd(), SW_HIDE);

BEGIN_EVENTSINK_MAP(CsetRouteDlg, CDHtmlDialog)
ON_EVENT(CsetRouteDlg, IDC_EXPLORER1, 259, CsetRouteDlg::DocumentCompleteExplorer, VTS_DISPATCH VTS_PVARIANT)
END_EVENTSINK_MAP()


void CsetRouteDlg::DocumentCompleteExplorer(LPDISPATCH pDisp, VARIANT* URL)
{
	CComQIPtr<IHTMLDocument3> spDocument;
	CComPtr<IHTMLElement> spElement2;
	CComQIPtr<IHTMLInputElement> spInputElement;
	BSTR myinputbstr;

	MessageBox(L"加载完成");

	spDocument = myExPlorer.get_Document();
	spDocument->getElementById(L"external_network_config", &spElement2);    //填入用户名
	spElement2->click();
	spElement2.Release();

	spDocument = myExPlorer.get_Document();
	spDocument->getElementById(L"internet_set", &spElement2);    //填入用户名
	spElement2->click();
	if (spElement2 != NULL)
	{
		MessageBox(L"连接成功");
	}
	else
	{
		MessageBox(L"连接失败");
	}

	spElement2.Release();


	spDocument = myExPlorer.get_Document();
	spDocument->getElementById(L"wan_setup_ip2", &spElement2);    //填入用户名
	spInputElement = spElement2;
	CString myStr;
	myinputbstr = myStr.AllocSysString();
	spInputElement->get_value(&myinputbstr);
	((CEdit*)GetDlgItem(IDC_EDIT_IP))->SetWindowTextW(myinputbstr);

	isConnect = 1;
	// TODO:  在此处添加消息处理程序代码
}

DocumentCompleteExplorer事件处理函数用于当网址页面加载完成后,将被回调,这个事件在控件里可以添加。

当连接成功后,将能正常看到路由器的界面,并且读回路由器静态IP的地址,代码里对应的ID号或NAME可以用浏览器去查看元素得到某个网页元素的信息,我这里的信息是对应磊科路由器的。


配置方法如下:(在这里特别说一下,一般来说网页上的控件都有独立的ID号,那么用getElementById方法去操作比较方便,只要有ID,不管网页上的是按钮还是输入框都能正常的操作。 然而,磊科路由器这里的用于提交表单的按钮却没有ID号,只有name属性,导致不能用原来的方法来达到目的。getElementsByName方法跟ID方法还是很有区别的,查了挺久MSDN都没找到用法。 后来Google后发现了一种方法,用QueryInterface方法能解决我的问题,哈哈,实在太好了。)

void CsetRouteDlg::OnBnClickedStep()
{
	if (isConnect == 0)
	{
		MessageBox(L"请先连接设备!");
		return;
	}

	CString editIP;
	((CEdit*)GetDlgItem(IDC_EDIT_IP))->GetWindowTextW(editIP);


	CComQIPtr<IHTMLInputElement> spInputElement;
	CComQIPtr<IHTMLDocument3> spDocument = myExPlorer.get_Document();
	CComPtr<IHTMLElement> spElement;
	 
	BSTR myinputbstr;
	CComPtr<IHTMLElement> spElement2;
	myinputbstr = editIP.AllocSysString();


	spDocument = myExPlorer.get_Document();
	spDocument->getElementById(L"wan_setup_ip2", &spElement2);    //填入用户名
	spInputElement = spElement2;


	myinputbstr = editIP.AllocSysString();
	spInputElement->put_value(myinputbstr);
	

	CComQIPtr<IHTMLElementCollection>  spInputCollect;
	spDocument->getElementsByName(L"submitbutton", &spInputCollect);
	LONG lLength = 0;
	VARIANT varIndex, var2;
	HRESULT hr;
	hr = spInputCollect->get_length(&lLength);
	if (FAILED(hr))
		return;

	for (int i = 0; i<lLength; i++){
		varIndex.vt = VT_UINT;
		varIndex.lVal = i;
		VariantInit(&var2);
		IDispatch * pDispatch;
		hr = spInputCollect->item(varIndex, var2, &pDispatch);
		if (FAILED(hr))
			continue;
		IHTMLElement *pFormElem = NULL;
		hr = pDispatch->QueryInterface(IID_IHTMLElement, (void**)&pFormElem);
		if (FAILED(hr))
			continue;
		pFormElem->click();
	}

	MessageBox(L"设置成功");

		// TODO:  在此添加控件通知处理程序代码
}

点击“配置”后,将会把文本框里IP值设置到路由器上,达到了模拟操作路由界面效果。


总结一下,模拟操作网页其实跟JS差不多,用起来还是挺方便的。 但在开发过程,我发现一些问题,我在加载过程中都加入了一些阻塞型的语句,比如MessageBox,然后用起来才正常,如果去掉这些阻塞型语句,我发现无法得到document整张页面,表现为在操作控件时出错了,这大概是加载异步的原因吧,当我模拟点击了某个按钮,页面响应来不及或都还没被刷新,此时去getElement就会出错。这个问题希望有人能给我提些看法,谢谢!

VS2013工程链接:点击打开链接


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值