使用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指針的方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM