開源小工具一:獲取客戶端內嵌IE控件(Internet Explorer_Server)的URL

前言:

做客戶端開發的很多時候,我們需要查看別人的客戶端裏面嵌入的網頁,查看裏面的JS等等,於是就寫了一個簡單的工具來獲取這些嵌入IE的客戶端使用的地址。

原理:

開啓一個後臺線程,不斷獲取當前鼠標所在位置的窗口句柄,通過這個句柄判斷窗口class是不是IE的Internet Explorer_Server,然後通過COM接口來獲取IE對象,通過接口獲取其內部鏈接的URL地址。爲了提高效率,使用快捷鍵來捕獲和停止捕獲。使用時,Alt+B開啓捕獲,移動鼠標到IE網頁上面後就會獲得地址了,然後Alt+S停止捕獲,就可以去複製鏈接的URL了。

<span style="font-family: Arial, Helvetica, sans-serif;">// MainDlg.h : interface of the CMainDlg class</span>
//
/////////////////////////////////////////////////////////////////////////////

#pragma once
#include <string>
using std::wstring;
#define WM_GETNEW_WND	WM_USER+100
#define WM_HOTKEY_BASE	100


inline bool operator != (const RECT& rc1, const RECT& rc2)
{
	return ((rc1.left!=rc2.left)
		|| (rc1.top!=rc2.top)
		|| (rc1.right!=rc2.right)
		|| (rc1.bottom!=rc2.bottom));
}

class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
	static bool s_bThreadSwitch;
	static bool s_bRunning;
	static HBRUSH s_hFrameBrush;
	HWND m_hEditWnd;
	enum { IDD = IDD_MAINDLG };
	CMainDlg()
		:m_hEditWnd(NULL)
	{

	}
	BEGIN_MSG_MAP(CMainDlg)
		MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
		MESSAGE_HANDLER(WM_GETNEW_WND, OnGetNewWindow)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(IDOK, OnOK)
		COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// center the dialog on the screen
		CenterWindow();
		// set icons
		HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
		SetIcon(hIcon, TRUE);
		HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
		SetIcon(hIconSmall, FALSE);
		m_hEditWnd=::GetDlgItem(m_hWnd, IDC_EDIT1);
		::SetDlgItemText(m_hWnd, IDC_STATUS_BAR, L"窗口捕獲未開啓,Alt+B立即開啓");
		::RegisterHotKey(m_hWnd, WM_HOTKEY_BASE+0, MOD_ALT, 0x42);
		::RegisterHotKey(m_hWnd, WM_HOTKEY_BASE+1, MOD_ALT, 0x53);
		s_hFrameBrush=::CreateSolidBrush(0xff0000);
		::SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE)|WS_EX_TOPMOST);
		return TRUE;
	}

	LRESULT OnGetNewWindow(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if ( NULL==m_hEditWnd )
			return 0;
		HWND hWnd=(HWND)wParam;
		if ( hWnd==m_hEditWnd )
		{
			::SetWindowText(m_hEditWnd, L"");
			return 0;
		}
		WCHAR szText[MAX_PATH+1]={0};
		LRESULT lSize=::SendMessage(hWnd, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szText);
		if ( lSize==0 )
			wcscpy(szText, L"窗口標題爲空");
		WCHAR szClassName[100]={0};
		::GetClassName(hWnd, szClassName, 100);
		CComBSTR url;
		if ( wcsncmp(szClassName, L"Internet Explorer_Server", 24) == 0 )
		{//此窗口爲內嵌IE控件
			UINT uMsg=::RegisterWindowMessage(L"WM_HTML_GETOBJECT");
			DWORD_PTR dwRetPtr;
			LRESULT lRet=::SendMessageTimeout(hWnd, uMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, &dwRetPtr);
			CComQIPtr<IHTMLDocument> docPtr;
			HRESULT hr=::ObjectFromLresult((LRESULT)dwRetPtr, IID_IHTMLDocument, 0, (void**)&docPtr);
			if ( SUCCEEDED(hr) && docPtr )
			{
				CComQIPtr<IDispatch> scriptPtr;
				hr=docPtr->get_Script(&scriptPtr);
				if ( SUCCEEDED(hr) && scriptPtr )
				{
					CComQIPtr<IHTMLWindow2> htmlwndPtr=scriptPtr;
					IHTMLDocument2* pDoc2;
					hr=htmlwndPtr->get_document(&pDoc2);
					if ( SUCCEEDED(hr) && pDoc2 )
					{
						pDoc2->get_URL(&url);
						pDoc2->Release();
					}
				}
			}
		}
		wstring strText(szText);
		strText.append(L"\r\n");
		strText.append(szClassName);
		if ( url.Length()>0 )
		{
			strText.append(L"\r\n");
			strText.append(url);
		}
		::SendMessage(m_hEditWnd, WM_SETTEXT, 0, (LPARAM)strText.c_str());
		bHandled=TRUE;
		return 0;
	}

	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if ( s_hFrameBrush )
		{
			::DeleteObject(s_hFrameBrush);
			s_hFrameBrush=NULL;
		}
		::UnregisterHotKey(m_hWnd, WM_HOTKEY_BASE+0);
		::UnregisterHotKey(m_hWnd, WM_HOTKEY_BASE+1);
		s_bThreadSwitch=false;
		while( s_bRunning )
			::Sleep(100);
		return 0;
	}

	LRESULT OnHotKey(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		switch( wParam )
		{
		case WM_HOTKEY_BASE+0: 
			BeginTrackWnd();
			break;
		case WM_HOTKEY_BASE+1:
			StopTrackWnd();
			break;
		default:
			break;
		}
		return 0;
	}

	LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CSimpleDialog<IDD_ABOUTBOX, FALSE> dlg;
		dlg.DoModal();
		return 0;
	}

	LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		// TODO: Add validation code 
		EndDialog(wID);
		return 0;
	}

	LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		EndDialog(wID);
		return 0;
	}

	void BeginTrackWnd()
	{
		if ( !s_bRunning )
		{
			s_bThreadSwitch=true;
			HANDLE hThread=::CreateThread(NULL, 0, MouseThread, m_hWnd, 0, NULL);
			::CloseHandle(hThread);
			::SetDlgItemText(m_hWnd, IDC_STATUS_BAR, L"窗口捕獲已經開啓,獲得IE鏈接後,Alt+S結束捕獲");
		}
	}

	void StopTrackWnd()
	{
		if ( s_bRunning )
		{
			s_bThreadSwitch=false;
			::SetDlgItemText(m_hWnd, IDC_STATUS_BAR, L"窗口捕獲未開啓,Alt+B立即開啓");
		}
	}

	static DWORD __stdcall MouseThread(LPVOID lpParam)
	{
		s_bRunning=true;
		POINT ptCur={0,0};
		HWND hMsgWnd=(HWND)lpParam;
		HWND hPreWnd=NULL;
		RECT rcWnd={0,0,0,0}, rcPrev={-1,-1,-1.-1};
		HWND hDeskWnd=::GetDesktopWindow();
		while( s_bThreadSwitch )
		{
			::GetCursorPos(&ptCur);
			HWND hWnd=::WindowFromPoint(ptCur);
			if ( NULL!=hWnd && hPreWnd!=hWnd )
			{
				::PostMessage(hMsgWnd, WM_GETNEW_WND, (WPARAM)hWnd, 0);
				hPreWnd=hWnd;
				if ( rcPrev!=rcWnd )
				{
					::InflateRect(&rcPrev, 10, 10);
					::InvalidateRect(hDeskWnd, NULL, TRUE);
					HDC hDC=::GetDC(hDeskWnd);
					RECT rcWnd;
					::GetWindowRect(hWnd, &rcWnd);
					::FrameRect(hDC, &rcWnd, s_hFrameBrush);
					::ReleaseDC(hDeskWnd, hDC);
					rcPrev=rcWnd;
				}
			}
			Sleep(100);
		}
		s_bRunning=false;
		return 0;
	}
};

bool CMainDlg::s_bThreadSwitch=true;
bool CMainDlg::s_bRunning=false;
HBRUSH CMainDlg::s_hFrameBrush=NULL;

當時寫這份代碼的時候用的是WTL,所以一長段代碼都在一個頭文件裏面。注意的是,COM初始化一定要在使用COM組件前:::CoInitialize(NULL);main函數退出前:::CoUninitialize();

實際使用:

獲取騰訊電腦管家軟件管理裏面嵌入的IE控件地址:


騰訊使用的居然是本地靜態 頁面,file://C:\ProgramData\Application Data\Tencent\QQPCMgr\SoftMgr\index-v3.html?version=11.0.16779.224&guid=642DC05B88DE6E170F23A791DC7623FC&from=0&featurever=3。我們還可以用瀏覽器打開,查看裏面JS的調用,JS與客戶端C++的調用在這裏不做介紹,前面的文章說過了:http://blog.csdn.net/mfcing/article/details/44540683

360的IE空間捕獲不到,應該是那個老流氓做了處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章