赞
踩
spy++(spyxx)是VS自带的开发工具,再VS安装目录下的tools文件夹下可以找到。
它可以看到所有一已经打开的窗口的句柄
使用方法:
Ctrl+F打开搜索窗口,鼠标拖动红框的图标,放到窗口上面,就可以获取到窗口的句柄信息
点击确认可以看到详细信息
点击同步可以自动定位到目录树上的位置
在目录树上就可以看到这个窗口下的所有控件的句柄信息
在上面的方法中我们已经获取到了这个窗口的所有句柄信息。在这四个句柄中我们只关心开两个控件,
即 确认Button 和 Edit输入框
目标确认,开始获取:
我们要引用user32.dll中的本地方法,主要是下面四个:
//根据窗口类型或者窗口标题获取窗口句柄 [DllImport("User32.dll", EntryPoint = "FindWindow")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); //根据父窗口句柄、子窗口句柄、窗口类型、窗口标题 获取句柄 [DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true)] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); /// <summary> /// 向指定句柄的窗口发送消息 /// </summary> /// <param name="hWnd">窗口句柄</param> /// <param name="Msg">消息类型</param> /// <param name="wParam">消息1</param> /// <param name="lParam">消息2</param> /// <returns></returns> [DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); //将指定句柄的窗口置顶 [DllImport("User32.dll", EntryPoint = "SetForegroundWindow")] private static extern bool SetForegroundWindow(IntPtr hWnd);
上述SendMessage中的第二个参数Msg类型种类很多,我们主要使用以下两个
const int WM_SETTEXT = 0x000C; //为指定句柄的窗口设置文本信息
const int WM_CLICK = 0x00F5; //为指定句柄的窗口发送点击事件
具体实现代码如下:
//根据窗口名称获取出啊港口句柄 IntPtr IPWnd = new IntPtr(0); IPWnd = FindWindow(null, "运维客户端"); if (IPWnd != IntPtr.Zero) { //根据找到的窗口 找到里面的输入框 IntPtr txtWnd = new IntPtr(0); txtWnd = FindWindowEx(IPWnd, IntPtr.Zero, "Edit", null); if (txtWnd != IntPtr.Zero) { //如果找到了,就往里面输入文本信息 SendMessage(txtWnd, WM_SETTEXT, IntPtr.Zero, "文本信息"); } //对于存在相同类型的控件,寻找起来是相对麻烦一些的,因为他们没有独特的标志,但是有独自的index //如该例中的Button ,我们可以通过index获取想要的控件句柄 //但是因为该按钮是第一个,所以默认找到的就是它,可以不做特殊处理 //如果要按照INDEX获取 可以使用下面的 FindWindowByIndex 方法 IntPtr buttonQRWnd = new IntPtr(0); buttonQRWnd = FindWindowEx(IPWnd, IntPtr.Zero, null, null); if (buttonQRWnd != IntPtr.Zero) { //将窗体置顶 点击事件要确保被点击的单位在最顶层,要不然点不到 SetForegroundWindow(IPWnd); //在任何操作之前最好等待一下,在这里主要避免置顶操作还未完成就触发点击事件,从而导致点击失效 Thread.Sleep(150); //给按钮发送点击消息 SendMessage(buttonQRWnd, WM_CLICK, IntPtr.Zero, ""); } }
static IntPtr FindWindowByIndex(IntPtr hWndParent, int index) { if (index == 0) return hWndParent; else { int ct = 0; IntPtr result = IntPtr.Zero; do { result = FindWindowEx(hWndParent, result, "Button", null); if (result != IntPtr.Zero) ++ct; } while (ct < index && result != IntPtr.Zero); return result; } }
获取句柄的步骤都是一样的,只不过在这种情况下我们基本上只能获取到最外层的窗体内容,里面的内容都是Html的,我们获取不到句柄,所以我们需要使用一个利器 mshtml,可以获取到指定句柄窗体内的 IHTMLDocument ,进而获取到指定元素。
通过 NuGet 安装 mshtml
基础使用代码如下:
//获取主窗口句柄 IntPtr LoginWnd = new IntPtr(0); LoginWnd = FindWindow("OMClientPlus", null); if (LoginWnd != IntPtr.Zero) { //下面的操作都是为了找到最里面的控件的句柄 //也就是sehlln内包含了shellView,shellView内又包含了ies ,最终ies才是承载html的容器控件 //视情况按照Spy++中显示的控件包含关系确认最终的控件信息 IntPtr shell = FindWindowEx(LoginWnd,IntPtr.Zero, "Shell Embedding",null); Thread.Sleep(50); IntPtr shellview = FindWindowEx(shell, IntPtr.Zero, "Shell DocObject View", null); Thread.Sleep(50); IntPtr ies = FindWindowEx(shellview, IntPtr.Zero, "Internet Explorer_Server", null); Thread.Sleep(50); //获取容器控件中的HtmlDoucument mshtml.IHTMLDocument2 id = GetHtmlDocument(ies.ToInt32()); //获取到所有的Input类型的组件 mshtml.IHTMLElementCollection inputs; inputs = (mshtml.IHTMLElementCollection)id.all.tags("input"); //找到用户名 mshtml.IHTMLElement accountElement = (mshtml.IHTMLElement)inputs.item("u",0); mshtml.IHTMLInputElement accountInputElement = (mshtml.IHTMLInputElement)accountElement; accountInputElement.value = account; Thread.Sleep(150); //找到密码 mshtml.IHTMLElement passwordElement = (mshtml.IHTMLElement)inputs.item("p", 0); mshtml.IHTMLInputElement passwordInputElement = (mshtml.IHTMLInputElement)passwordElement; passwordInputElement.value = password; Thread.Sleep(150); //点击确认按钮 mshtml.IHTMLElement login = (mshtml.IHTMLElement)inputs.item("Login", 0); login.click(); }
public mshtml.IHTMLDocument2 GetHtmlDocument(int hwnd)
{
System.Object domObject = new System.Object();
int tempInt = 0;
System.Guid guidIEDocument2 = new Guid();
int WM_Html_GETOBJECT = Win32API.RegisterWindowMessage("WM_Html_GETOBJECT");//定义一个新的窗口消息
int W = Win32API.SendMessage(hwnd, WM_Html_GETOBJECT, 0, ref tempInt);//注:第二个参数是RegisterWindowMessage函数的返回值
int lreturn = Win32API.ObjectFromLresult(W, ref guidIEDocument2, 0, ref domObject);
mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)domObject;
return doc;
}
如上就是mshtml 的简单用法,更多使用方法还需不断深入探索。
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。