VC++ 通过COM操作IE浏览器

#pragma once
#include <windows.h>
#include <MsHTML.h>
#include <atlcomcli.h>
#include <oleacc.h>
#include <Tlhelp32.h>
#include <WtsApi32.h>
#pragma comment(lib,"Wtsapi32.lib")

#include <string>
#include <vector>
#include <codecvt>

// 窗口结构信息
typedef struct _window_info
{
	HWND h;
	std::wstring process;
	std::wstring title;
	std::wstring class_name;
	int pid;
	int x;
	int y;
	int width;
	int height;
}window_info, * pwindow_info;

// ie窗口的控件结构信息
typedef struct _ie_window_info_
{
	std::wstring type;
	std::wstring name;
	std::wstring value;
}ie_window_info, * pie_window_info;

namespace _ie_control
{
	// 初始化资源
	bool initialize();

	// 释放资源
	void release();

	// 获取字符串
	const wchar_t* get_wchar(HWND h, wchar_t* str, int size);

	// 字符串转化
	std::wstring string_to_wstring(std::string str);
	std::string wstring_to_string(std::wstring wstr);

	// 获取ie进程列表
	std::vector<window_info> get_iexplore_process();

	// 获取指定ie窗口句柄
	HWND get_ie_window_handle(HWND h);

	// 获取ie窗口的标题栏url
	std::wstring get_ie_url(HWND h);

	// 判断是否是IE窗口
	bool is_ie_window(HWND h);

	// 获取整个网页的接口
	IHTMLDocument2* get_ie_doc_interface_ex(HWND h);

	// 获取指定网页的密码
	std::vector<std::wstring> get_ie_password(IHTMLDocument2* doc);

	// 获取指定位置的控件信息
	ie_window_info get_ie_control_information_by_point(IHTMLDocument2* doc, unsigned int x, unsigned int y);

	// 获取ie网页的源代码
	bool get_ie_source_code(IHTMLDocument2* doc, wchar_t* source, unsigned int size);

	// 枚举指定网页的控件信息
	std::vector<ie_window_info> enum_ie_window_control(IHTMLDocument2* doc);

	// 设置账号或者密码
	bool set_ie_control_text(IHTMLDocument2* doc, std::wstring type, std::wstring name, std::wstring value);

	// 提交表单(点击登陆按钮)
	bool submit_form(IHTMLDocument2* doc);
}
#include "ie_control.h"

static std::vector<int> get_process_id(std::wstring session_name, std::wstring application_name)
{
	std::vector<int> result;

	DWORD dwCount = 0;
	PWTS_PROCESS_INFOW pi = { 0 };
	DWORD dwSize = 0;
	wchar_t username[128] = { 0 };
	SID_NAME_USE nameuse = SidTypeUser;

	if (WTSEnumerateProcessesW(NULL, 0, 1, &pi, &dwCount))
	{
		for (DWORD i = 0; i < dwCount; i++)
		{
			dwSize = 128;
			memset(username, 0, sizeof(wchar_t) * 128);
			if (LookupAccountSidW(NULL, pi[i].pUserSid, username, &dwSize, NULL, &dwSize, &nameuse))
			{
				if (session_name == std::wstring{ username }
					&& application_name == std::wstring{ pi[i].pProcessName })
				{
					result.push_back(pi[i].ProcessId);
				}
			}
		}

		WTSFreeMemory(pi);
	}

	return result;
}

static std::wstring get_process_name_by_id(int id)
{
	std::wstring ret;

	HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (h == INVALID_HANDLE_VALUE) return ret;

	PROCESSENTRY32W pro{ 0 };
	pro.dwSize = sizeof(pro);

	if (Process32FirstW(h, &pro))
	{
		do
		{
			if (pro.th32ProcessID == id)
				ret = pro.szExeFile;
		} while (Process32NextW(h, &pro));
	}

	CloseHandle(h);
	return ret;
}

static bool __stdcall enum_window_callback(HWND h, LPARAM l)
{
	std::vector<window_info>* windows = (std::vector<window_info>*)l;

	if (GetWindowLongA(h, GWL_STYLE) & WS_VISIBLE)
	{
		DWORD pid = 0;
		GetWindowThreadProcessId(h, &pid);

		wchar_t title[0x50]{ 0 };
		_ie_control::get_wchar(h, title, 0x50);

		wchar_t class_name[0x50]{ 0 };
		GetClassNameW(h, class_name, 0x50);

		RECT r{ 0 };
		GetWindowRect(h, &r);

		window_info info{ 0 };
		info.h = h;
		info.process = get_process_name_by_id(pid);
		info.title = title;
		info.class_name = class_name;
		info.pid = pid;
		info.x = r.left;
		info.y = r.top;
		info.width = r.right - r.left;
		info.height = r.bottom - r.top;
		windows->push_back(info);
	}

	return true;
}

static bool __stdcall enum_subwindow_callback(HWND h, LPARAM l)
{
	std::vector<window_info>* windows = (std::vector<window_info>*)l;

	if (GetWindowLongA(h, GWL_STYLE) & WS_VISIBLE)
	{
		wchar_t class_name[0x50]{ 0 };
		GetClassNameW(h, class_name, 0x50);

		wchar_t title[0x50]{ 0 };
		_ie_control::get_wchar(h, title, 0x50);

		RECT r{ 0 };
		GetWindowRect(h, &r);

		window_info info{ 0 };
		info.h = h;
		info.class_name = class_name;
		info.title = title;
		info.x = r.left;
		info.y = r.top;
		info.width = r.right - r.left;
		info.height = r.bottom - r.top;
		windows->push_back(info);

		EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)windows);
	}

	return true;
}

namespace _ie_control
{
	bool initialize()
	{
		return CoInitialize(NULL) == S_OK;
	}

	void release()
	{
		CoUninitialize();
	}

	const wchar_t* get_wchar(HWND h, wchar_t* str, int size)
	{
		SendMessageW(h, WM_GETTEXT, size, (LPARAM)str);
		return str;
	}

	std::wstring string_to_wstring(std::string str)
	{
		using convert_typeX = std::codecvt_utf8<wchar_t>;
		std::wstring_convert<convert_typeX, wchar_t> converterX;
		return converterX.from_bytes(str);
	}

	std::string wstring_to_string(std::wstring wstr)
	{
		using convert_typeX = std::codecvt_utf8<wchar_t>;
		std::wstring_convert<convert_typeX, wchar_t> converterX;
		return converterX.to_bytes(wstr);
	}

	std::vector<window_info> get_iexplore_process()
	{
		std::vector<window_info> windows;
		EnumWindows((WNDENUMPROC)enum_window_callback, (LPARAM)&windows);

		std::vector<window_info> ret;
		for (const auto& it : windows)
			if (it.process == L"iexplore.exe" && it.class_name == L"IEFrame")
				ret.push_back(it);

		return ret;
	}

	HWND get_ie_window_handle(HWND h)
	{
		std::vector<window_info> all_controls;
		if (EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)&all_controls))
			for (const auto& it : all_controls)
				if (it.class_name == L"Internet Explorer_Server")
					return it.h;

		return 0;
	}

	std::wstring get_ie_url(HWND h)
	{
		std::vector<window_info> ie_windows;
		if (EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)&ie_windows))
			for (const auto& it : ie_windows)
				if (it.title.find(L"http") != std::string::npos)
					return it.title;

		return L"";
	}

	bool is_ie_window(HWND h)
	{
		if (h == NULL) return false;

		wchar_t class_name[0x50]{ 0 };
		int ret = GetClassNameW(h, class_name, 0x50);
		if (ret == 0) return false;

		return std::wstring{ L"Internet Explorer_Server" } == class_name;
	}

	IHTMLDocument2* get_ie_doc_interface_ex(HWND h)
	{
		IHTMLDocument2* ret = nullptr;

		if (is_ie_window(h) == false) return ret;

		static HINSTANCE oleacc_module = LoadLibraryW(L"OLEACC.DLL");
		if (oleacc_module == nullptr) return ret;

		static LPFNOBJECTFROMLRESULT pf_ObjectFromLresult = (LPFNOBJECTFROMLRESULT)GetProcAddress(oleacc_module, "ObjectFromLresult");
		if (pf_ObjectFromLresult == nullptr) return ret;

		LRESULT res;
		SendMessageTimeoutW(h, RegisterWindowMessageW(L"WM_HTML_GETOBJECT"), 0, 0, SMTO_ABORTIFHUNG, 1000, (DWORD_PTR*)&res);

		CComPtr<IHTMLDocument> doc = NULL;
		HRESULT hr = pf_ObjectFromLresult(res, IID_IHTMLDocument, 0, (void**)&doc);
		if (FAILED(hr)) return ret;

		CComPtr<IDispatch> disp;
		CComQIPtr<IHTMLWindow2> win;
		doc->get_Script(&disp);
		win = disp;
		if (win) win->get_document(&ret);

		return ret;
	}

	std::vector<std::wstring> get_ie_password(IHTMLDocument2* doc)
	{
		std::vector<std::wstring> passwords;
		CComPtr<IHTMLElementCollection> form_coll;
		long len_form = 0;

		if (doc == nullptr) return passwords;
		if (FAILED(doc->get_forms(&form_coll))) return passwords;
		if (FAILED(form_coll->get_length(&len_form)))  return passwords;

		VARIANT v_index, v_id;
		CComPtr<IDispatch> disp;

		for (long i = 0; i < len_form; i++)
		{
			V_VT(&v_id) = VT_I4;
			V_I4(&v_id) = i;
			V_VT(&v_index) = VT_I4;
			V_I4(&v_index) = 0;

			if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
			{
				CComPtr<IHTMLFormElement> form_item;
				if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
				{
					long len_item = 0;
					if (SUCCEEDED(form_item->get_length(&len_item)))
					{
						for (long j = 0; j < len_item; j++)
						{
							V_VT(&v_id) = VT_I4;
							V_I4(&v_id) = j;
							V_VT(&v_index) = VT_I4;
							V_I4(&v_index) = 0;

							CComPtr<IHTMLInputTextElement> input;
							if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
							{
								if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
								{
									CComBSTR c_type;
									HRESULT hr = input->get_type(&c_type);

									if (SUCCEEDED(hr)
										&& c_type
										&& c_type.Length()
										&& c_type.ToLower() == S_OK
										&& std::wstring{ c_type } == std::wstring{ L"password" })
									{
										CComBSTR c_value;
										hr = input->get_value(&c_value);

										if (SUCCEEDED(hr) && c_value && c_value.Length())
										{
											passwords.push_back(std::wstring(c_value.m_str));
										}
									}
								}
							}
						}
					}
				}
			}
		}
		return passwords;
	}

	ie_window_info get_ie_control_information_by_point(IHTMLDocument2* doc, unsigned int x, unsigned int y)
	{
		ie_window_info ret;

		if (doc == nullptr) return ret;

		CComPtr<IHTMLElement> element;
		HRESULT hr = doc->elementFromPoint(x, y, &element);
		if (FAILED(hr)) return ret;

		CComPtr<IHTMLInputTextElement> input_element;
		hr = element->QueryInterface(IID_IHTMLInputTextElement, (void**)&input_element.p);
		if (FAILED(hr)) return ret;

		CComBSTR c_type;
		hr = input_element->get_type(&c_type);
		if (SUCCEEDED(hr) && c_type)
			ret.type = c_type.m_str;

		CComBSTR c_value;
		hr = input_element->get_value(&c_value);
		if (SUCCEEDED(hr) && c_value)
			ret.value = c_value.m_str;

		CComBSTR c_name;
		hr = input_element->get_name(&c_name);
		if (SUCCEEDED(hr) && c_name)
			ret.name = c_name.m_str;

		return ret;
	}

	bool get_ie_source_code(IHTMLDocument2* doc, wchar_t* source, unsigned int size)
	{
		if (doc == nullptr) return false;
		if (source == nullptr) return false;
		if (size <= 0) return false;

		CComPtr<IHTMLElementCollection> all_coll;
		HRESULT hr = doc->get_all(&all_coll);
		if (FAILED(hr)) return false;

		long length = 0;
		hr = all_coll->get_length(&length);
		if (FAILED(hr)) return false;

		for (long i = 0; i < length; i++)
		{
			VARIANT v_index, v_name;
			v_name.vt = v_index.vt = VT_I4;
			v_name.lVal = v_index.lVal = i;

			CComPtr<IDispatch> disp;
			hr = all_coll->item(v_name, v_index, &disp);
			if (SUCCEEDED(hr))
			{
				CComPtr<IHTMLElement> element;
				hr = disp->QueryInterface(IID_IHTMLElement, (void**)&element);
				if (SUCCEEDED(hr))
				{
					CComBSTR c_name;
					hr = element->get_tagName(&c_name);
					if (SUCCEEDED(hr) && c_name && c_name.Length())
					{
						if (SUCCEEDED(c_name.ToLower()) && c_name.m_str == std::wstring{ L"html" })
						{
							CComBSTR content;
							hr = element->get_outerHTML(&content);
							if (SUCCEEDED(hr) && content)
							{
								unsigned int len = content.Length();
								if (len < size)
								{
									memcpy(source, content.m_str, len);
									return true;
								}
							}
						}
					}
				}
			}
		}
		return false;
	}

	std::vector<ie_window_info> enum_ie_window_control(IHTMLDocument2* doc)
	{
		std::vector<ie_window_info> ret;
		CComPtr<IHTMLElementCollection> form_coll;
		long len_form = 0;

		if (doc == nullptr) return ret;
		if (FAILED(doc->get_forms(&form_coll))) return ret;
		if (FAILED(form_coll->get_length(&len_form)))  return ret;

		VARIANT v_index, v_id;
		CComPtr<IDispatch> disp;

		for (long i = 0; i < len_form; i++)
		{
			V_VT(&v_id) = VT_I4;
			V_I4(&v_id) = i;
			V_VT(&v_index) = VT_I4;
			V_I4(&v_index) = 0;

			if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
			{
				CComPtr<IHTMLFormElement> form_item;
				if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
				{
					long len_item = 0;
					if (SUCCEEDED(form_item->get_length(&len_item)))
					{
						for (long j = 0; j < len_item; j++)
						{
							V_VT(&v_id) = VT_I4;
							V_I4(&v_id) = j;
							V_VT(&v_index) = VT_I4;
							V_I4(&v_index) = 0;

							CComPtr<IHTMLInputTextElement> input;
							CComPtr<IHTMLInputButtonElement> button;

							if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
							{
								// 输入控件
								if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
								{
									ie_window_info info;

									CComBSTR c_type;
									HRESULT hr = input->get_type(&c_type);
									if (SUCCEEDED(hr) && c_type)
										info.type = c_type.m_str;

									CComBSTR c_value;
									hr = input->get_value(&c_value);
									if (SUCCEEDED(hr) && c_value)
										info.value = c_value.m_str;

									CComBSTR c_name;
									hr = input->get_name(&c_name);
									if (SUCCEEDED(hr) && c_name)
										info.name = c_name.m_str;

									ret.push_back(info);
								}

								// 按钮控件
								else if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputButtonElement, (void**)&button.p)))
								{
									ie_window_info info;

									CComBSTR c_type;
									HRESULT hr = button->get_type(&c_type);
									if (SUCCEEDED(hr) && c_type)
										info.type = c_type.m_str;

									CComBSTR c_value;
									hr = button->get_value(&c_value);
									if (SUCCEEDED(hr) && c_value)
										info.value = c_value.m_str;

									CComBSTR c_name;
									hr = button->get_name(&c_name);
									if (SUCCEEDED(hr) && c_name)
										info.name = c_name.m_str;

									ret.push_back(info);
								}
							}
						}
					}

					// form_item->submit(); // 提交表单
				}
			}
		}
		return ret;
	}

	bool set_ie_control_text(IHTMLDocument2* doc, std::wstring type, std::wstring name, std::wstring value)
	{
		CComPtr<IHTMLElementCollection> form_coll;
		long len_form = 0;

		if (doc == nullptr) return false;
		if (FAILED(doc->get_forms(&form_coll))) return false;
		if (FAILED(form_coll->get_length(&len_form)))  return false;

		VARIANT v_index, v_id;
		CComPtr<IDispatch> disp;
		bool ret = false;

		for (long i = 0; i < len_form; i++)
		{
			V_VT(&v_id) = VT_I4;
			V_I4(&v_id) = i;
			V_VT(&v_index) = VT_I4;
			V_I4(&v_index) = 0;

			if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
			{
				CComPtr<IHTMLFormElement> form_item;
				if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
				{
					long len_item = 0;
					if (SUCCEEDED(form_item->get_length(&len_item)))
					{
						for (long j = 0; j < len_item; j++)
						{
							V_VT(&v_id) = VT_I4;
							V_I4(&v_id) = j;
							V_VT(&v_index) = VT_I4;
							V_I4(&v_index) = 0;

							CComPtr<IHTMLInputTextElement> input;
							if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
							{
								if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
								{
									CComBSTR c_type;
									input->get_type(&c_type);

									CComBSTR c_name;
									input->get_name(&c_name);

									if (c_type && c_name && c_type.m_str == type && c_name.m_str == name)
									{
										CComBSTR c_value = value.c_str();
										HRESULT hr = input->put_value(c_value);
										ret = SUCCEEDED(hr);
									}
								}
							}
						}
					}
				}
			}
		}

		return ret;
	}

	bool submit_form(IHTMLDocument2* doc)
	{
		CComPtr<IHTMLElementCollection> form_coll;
		long len_form = 0;

		if (doc == nullptr) return false;
		if (FAILED(doc->get_forms(&form_coll))) return false;
		if (FAILED(form_coll->get_length(&len_form)))  return false;

		bool ret = false;
		VARIANT v_index, v_id;
		CComPtr<IDispatch> disp;

		for (long i = 0; i < len_form; i++)
		{
			V_VT(&v_id) = VT_I4;
			V_I4(&v_id) = i;
			V_VT(&v_index) = VT_I4;
			V_I4(&v_index) = 0;

			if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
			{
				CComPtr<IHTMLFormElement> form_item;
				if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
				{
					bool has_text = false;
					bool has_password = false;
					bool has_button = false;

					long len_item = 0;
					if (SUCCEEDED(form_item->get_length(&len_item)))
					{
						for (long j = 0; j < len_item; j++)
						{
							V_VT(&v_id) = VT_I4;
							V_I4(&v_id) = j;
							V_VT(&v_index) = VT_I4;
							V_I4(&v_index) = 0;

							CComPtr<IHTMLInputTextElement> input;
							CComPtr<IHTMLInputButtonElement> button;

							if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
							{
								// 输入控件
								if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
								{
									CComBSTR c_type;
									HRESULT hr = input->get_type(&c_type);
									if (SUCCEEDED(hr) && c_type && SUCCEEDED(c_type.ToLower()))
									{
										if (c_type.m_str == std::wstring{ L"text" }) has_text = true;
										else if (c_type.m_str == std::wstring{ L"password" }) has_password = true;
									}
								}

								// 按钮控件
								else if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputButtonElement, (void**)&button.p)))
								{
									CComBSTR c_type;
									HRESULT hr = button->get_type(&c_type);
									if (SUCCEEDED(hr) && c_type && SUCCEEDED(c_type.ToLower()))
										if (c_type.m_str == std::wstring{ L"submit" }) has_button = true;
								}
							}
						}
					}

					if (has_text && has_password && has_button)
					{
						form_item->submit(); // 提交表单
						ret = true;
					}
				}
			}
		}

		return ret;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值