使用IWebBrowser2操控浏览器页面测试(IE)

  测试一下在IE浏览器界面中插入代码测试,采用寻找窗口的方式获取Internet Explorer_Server句柄。
  写的时候参考了很多网上的资料,有些地方不大适用就稍微修改了一下。

  1. SendMessageTimeout函数一直无效(看网上有一回答说c#可以正常使用,没试过),无效情况是执行成功(非超时),但是lpRes为0,于是改用SendMessage;
  2. 使用spyxx查找IEFrame下的Internet Explorer_Server窗口,根据实际情况来寻找窗口,网上年代久远的部分代码只有三层;
  3. 似乎是因为main函数在退出时会释放程序执行过程中申请的所有资源的原因,在程序最后加上CoUninitialize()将导致win7下出现程序退出异常的情况,在win10下则不会;另一个解决办法是在CoUninitialize()后边使用ExitProcess()退出进程,但是可能有部分内存未释放;
  4. 测试代码时,在win7及以下平台系统中navigate2()方法无法使用,应使用navigate(),使用navigate()时BSTR类型的URL参数时使用SysAllocString初始化,虽然实际上是wchar*,但是使用常量初始化变量或者使用字符串拷贝函数wcscpy时会出错(迷);
  5. QueryService参数中的SID_SWebBrowserApp替换为IID_IWebBrowserApp

  这里将js代码写入页面需要运行的话,我是使用IHTMLDocument2write方法写回document,页面刷新执行js代码,但是页面部分样式可能丢失。除此之外,还有很多方法可以实现,比如利用事件响应等方法,而且也不一定插入js,插入iframe或者一条链接之类的无需刷新页面。

#include "windows.h"
#include "mshtml.h"
#include "stdio.h"
#include "ExDisp.h"
#include "atlbase.h"
#include "comutil.h"
#include "oleacc.h"

//#pragma comment(lib, "oleacc.lib")

//int WINAPI WinMain(HINSTANCE hins, HINSTANCE hPrev, LPSTR lpCmdLine, INT nCmdShow) {
INT main(int argc, char* argv[]){
	//IWebBrowser2 
	HWND hWnd_pre = NULL, hWnd_child = NULL, hWnd_IES = NULL;
	hWnd_pre = FindWindow("IEFrame", NULL);	//IE Window Class
	if (hWnd_pre == NULL) {
		OutputDebugString(TEXT("IE didnot open."));
	}

	hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("Shell DocObject View"), NULL);	// test
	if (hWnd_child == NULL) {	// not only three Layers
		hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("Frame Tab"), NULL);
		if (hWnd_child == NULL) {
			OutputDebugString(TEXT("not Found IE Tab."));
		}
		hWnd_pre = hWnd_child;
		hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("TabWindowClass"), NULL);
		hWnd_pre = hWnd_child;
		hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("Shell DocObject View"), NULL);
		hWnd_pre = hWnd_child;
		hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("Internet Explorer_Server"), NULL);
	}
	else {
		hWnd_pre = hWnd_child;
		hWnd_child = FindWindowEx(hWnd_pre, 0, TEXT("Internet Explorer_Server"), NULL);
	}
	hWnd_IES = hWnd_child;		// Get Internet Explorer_Server Window's Handle
	printf("handle value of Internet Explorer_Server => %#x\n", (DWORD*)hWnd_child);

	CoInitialize(0);   // for using of COM interfaces
	UINT nMsg = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT"));   // register common msg of between two windows
	if (nMsg)
		printf("success registe Window message WM_HTML_GETOBJECT, msg ID => %#x\n", nMsg);
	
	CComPtr<IHTMLDocument2> pHtmlDoc;
	LRESULT result;
	//if (!SendMessageTimeout(hWnd_IES, nMsg, 0, 0, SMTO_NORMAL, 30000, (LPDWORD)result)) {
	if (!(result = SendMessage(hWnd_IES, nMsg, 0, 0)))		// send message for associated value of msg
		printf("call sendMessageTimeout failed:( error code: %#x\n", GetLastError());
	else {
		printf("returned result value: %#x\n", result);
		/*if (!result) {
			printf("returned result id none...end");
			ExitProcess(1);
		}*/
		HMODULE hLib = LoadLibrary("oleacc.dll");
		LPFNOBJECTFROMLRESULT pFObjectFromLresult = (LPFNOBJECTFROMLRESULT)GetProcAddress(hLib, "ObjectFromLresult");
		//HRESULT hRes = ObjectFromLresult(result, IID_IHTMLDocument2, 0, (void**)&pHtmlDoc);
		HRESULT hRes = pFObjectFromLresult(result, IID_IHTMLDocument2, 0, (void**)&pHtmlDoc);
		if (SUCCEEDED(hRes)) {
			printf("get IHTMLDocument2 success :)\n");
			//OLECHAR urll[] = L"http://www.baidu.com/";
			CComPtr<IHTMLWindow2> spWnd2;
			CComPtr<IServiceProvider> spServiceProvider;
			IWebBrowser2* pWebBrow = NULL;
			hRes = pHtmlDoc->get_parentWindow((IHTMLWindow2**)&spWnd2);
			if (SUCCEEDED(hRes)) {
				hRes = spWnd2->QueryInterface(IID_IServiceProvider, (void**)&spServiceProvider);	// Query Interface
				if (SUCCEEDED(hRes)) {
					hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&pWebBrow);   // query service
					if (SUCCEEDED(hRes)) {
						printf("Get IWebBrowser handlw Success :)\n");

						////1-跳转测试
						//VARIANT PARAM;
						//VariantInit(&PARAM);
						////V_VT(&PARAM) = VT_I4;
						////V_I4(&PARAM) = navOpenInNewTab;	//open in new tab
						////hRes = pWebBrow->Navigate2(&CComVariant("http://www.baidu.com/"), 0, 0, 0, 0);// win7 and former versions not support.
						//BSTR URLL = SysAllocString(L"http://www.baidu.com/");
						//hRes = pWebBrow->Navigate(URLL, &PARAM, &PARAM, &PARAM, &PARAM);		// navigate
						//SysFreeString(URLL);
						//if (SUCCEEDED(hRes)) printf("navigate success :)\n");
						//else printf("navigate failed :(\n");
						
						///*//2-获取地址栏URL测试
						//hRes = pWebBrow->get_LocationURL(&URLLL);
						//if(SUCCEEDED(hRes))
						//	printf("Get URL : %ws\n", URLL);*/
						
						////3-write document
						//SAFEARRAY* pSafeArr = SafeArrayCreateVector(VT_VARIANT, 0, 1);
						//if (pSafeArr) {
						//	BSTR pInsertCode = SysAllocString(L"<script>alert('just a test')</script>");
						//	VARIANT *PARAM = NULL;
						//	SafeArrayAccessData(pSafeArr, (void**)&PARAM);
						//	V_VT(PARAM) = VT_BSTR;		// PARAM->vt = VT_BSTR
						//	V_BSTR(PARAM) = pInsertCode;	// PARAM->bStrVal
						//	SafeArrayUnaccessData(pSafeArr);
						//	pHtmlDoc->write(pSafeArr);	// will refresh
						//	pHtmlDoc->close();
						//	SafeArrayDestroy(pSafeArr);
						//	pSafeArr = NULL;
						//}
						

						//get HTML codes
						BSTR pText = SysAllocString(L"<script>alert('test')</script>");
						BSTR wheer = SysAllocString(L"afterBegin");	//代码放置位置
						CComPtr<IHTMLElement> pHtmlElem;
						pHtmlDoc->get_body(&pHtmlElem);
						
						//pHtmlElem->get_innerHTML(&pText);
						//pHtmlElem->put_innerHTML(pText);
						hRes = pHtmlElem->insertAdjacentHTML(wheer, pText); // 插入
						SysFreeString(pText);
						SysFreeString(wheer);
						pText = NULL;
						wheer = NULL;

						//重载页面
						if (SUCCEEDED(hRes)) {
							printf("insert html code SUCCESS:)\n");

							/*pHtmlElem->get_outerHTML(&pText);
							SAFEARRAY* pSafeArr = SafeArrayCreateVector(VT_VARIANT, 0, 1);
							VARIANT *PARAM = NULL;
							SafeArrayAccessData(pSafeArr, (void**)&PARAM);
							V_VT(PARAM) = VT_BSTR;
							V_BSTR(PARAM) = pText;
							SafeArrayUnaccessData(pSafeArr);
							pHtmlDoc->write(pSafeArr);
							pHtmlDoc->close();
							SafeArrayDestroy(pSafeArr);
							pSafeArr = NULL;*/
						}
						else
							printf("insert html code Failed:(\n");
						//printf("HTML Text (length: %#x): %ws\n", );
						//INT dwSize = wcslen(pText);
						//CHAR *pOutter = (CHAR*)malloc(dwSize);
						//WideCharToMultiByte(CP_ACP, 0, pText, dwSize, pOutter, dwSize, 0, 0);
						//FILE *fp = fopen("html.html", "w");
						////fprintf(fp, "%ws", pText);
						//fwrite(pOutter, wcslen(pText), 1, fp);
						//free(pOutter);
						//fclose(fp);

					}
					else printf("Get IWebBrowser handle Failed:(\n");
				}
				//pHtmlDoc->get_body(&pHtmlElem); //get_body(&pHtmlElem);
				//pHtmlElem->get_outerHTML(pText); //get_innerText(pText);
				//printf("GOT > \n%ws\n", pText);
				pWebBrow->Release();
				pWebBrow = NULL;
			}
			else
				printf("error returned Result Code: %#x\n", hRes);
		}
		else printf("get IHTMLDocument2 failed:(\n");
	}
	/*printf("%#x\n", hwd);

	PostMessage(hWnd_IES, WM_QUIT, 0, 0);
	PostMessage(hWnd_IES, WM_CLOSE, 0, 0);
	PostMessage(hWnd_IES, WM_DESTROY, 0, 0);*/
	/*CoUninitialize(); //添加则出现异常,可能是在程序退出时还会调用一次析构函数,以释放所有声明的变量
	ExitProcess(0);*/
}

  愈发感觉windows的不简单。
参考链接:

  1. MSDN
  2. 获取IWebBrowser2指针的方法
posted @ 2019-08-22 23:43  Bl0od  阅读(1588)  评论(0编辑  收藏  举报