当前位置:   article > 正文

C# 通过窗口句柄为指定窗口发送指令(user32.dll,mshtml)_user32 句柄

user32 句柄


本文中出要处理两种窗体的 句柄控制

  • 常规窗口:可以轻松获取到窗口的句柄信息,进而获取到窗口内的控件的句柄,以此类推最终获取到要定位的控件的句柄
  • 内嵌浏览内核:实际内容是一个网页,被包含在一个容器内

Spy++

spy++(spyxx)是VS自带的开发工具,再VS安装目录下的tools文件夹下可以找到。
它可以看到所有一已经打开的窗口的句柄
使用方法:
Ctrl+F打开搜索窗口,鼠标拖动红框的图标,放到窗口上面,就可以获取到窗口的句柄信息
在这里插入图片描述
在这里插入图片描述
点击确认可以看到详细信息
在这里插入图片描述
点击同步可以自动定位到目录树上的位置
在这里插入图片描述
在目录树上就可以看到这个窗口下的所有控件的句柄信息
在这里插入图片描述

获取常规窗口的句柄并传输命令

如图uoqu
在这里插入图片描述
在上面的方法中我们已经获取到了这个窗口的所有句柄信息。在这四个句柄中我们只关心开两个控件,
即 确认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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

上述SendMessage中的第二个参数Msg类型种类很多,我们主要使用以下两个

 const int WM_SETTEXT = 0x000C; //为指定句柄的窗口设置文本信息
 const int WM_CLICK = 0x00F5; //为指定句柄的窗口发送点击事件
  • 1
  • 2

具体实现代码如下:

//根据窗口名称获取出啊港口句柄
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, "");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

获取内嵌网页的窗体中的元素,并发送消息

获取句柄的步骤都是一样的,只不过在这种情况下我们基本上只能获取到最外层的窗体内容,里面的内容都是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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
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;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如上就是mshtml 的简单用法,更多使用方法还需不断深入探索。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/45184
推荐阅读
  • OpenGL如何渲染NV12数据引言参考资料创建纹理shader脚本如何readpixel回yuvByte流引言其实自己也是个GL小白,刚入门没多久。最近接手一个项目,由于种种原因吧,对接同学提供给我的是YUV(NV12)格式的byte流数... [详细]

  • 从2017年6月开始接触自动化至今,已经有好几年,从17年接触UI自动化(unittest+selenium)到18年接触接口自动化(unittest+requests)再到18年自己编写自动化平台(后台使用pythonflask,前端... [详细]

  • WindowsAPI函数大全,从事软件开发的朋友可以参考下1.API之网络函数WNetAddConnection创建同一个网络资源的永久性连接WNetAddConnection2创建同一个网络资源的连接WNetAddConnection3创... [详细]

  • GitHub这几年国内普通户越来越难以访问,github作为全球最大的开源平台,里面有的内容很多,不管是对专业户还是普通户,无法访问都是很严重的问题。_github不了了github不了了GitHub这几年国内普通户越来越难以... [详细]

  • C++全局数组的输出结果与在main函数中定义的数组有所不同。在全局数组中定义的元素的作用域是整个程序,可以在任何地方访问和使用。而在main函数中定义的数组的作用域只限于main函数内部,无法在其他函数或全局作用域中使用。因此,在输出全局... [详细]

  • 在C++中对于以下语句://全局域inti=3;intj=i;编译时将i放入.data段,设置其值为3。而对于j,编译器遇到这种语句,只知道j=i,由于i是变量,不是常量,编译器无法在编译时直接得到它的值,编译器只会找到i的地址,然后读取这... [详细]

  • 杜甫(公元712—公元770),原籍湖北襄阳,后徙河南巩县。字子美,自号少陵野老,杜少陵,杜工部等,唐代著名诗人,世称诗圣,生活在安史之乱(唐朝由盛转衰)时期的现实主义诗人,世称杜工部、杜拾遗,代表作三吏(《新安吏》《石壕吏》《潼关... [详细]

  • 引言Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodityhardware)上分布式文件系统。它和现有分布式文件系统有很多共同点。但同时,它和其他分布式文件系统区别也是很明显HDFS是一个高度容错性... [详细]

  • 1、序最近正好有时间,所以分析了一下某音APK,抓包看到后面绝大部分的请求都用到了install_id,odin_ttttreq、X-Gorgon、X-SS-STUB这些字段,今天简单分析一下,有不足之处,请板正,仅仅记录下学习的过程。2... [详细]

  • MongoDB批量写入操作MongoDB批量写入操作一、概述MongoDB为客户端提供了批量执行写入操作的能力。批量写入操作影响单个集合。MongoDB允许应用程序确定批量写入操作所需的可接受确认级别。db.collection.bulkW... [详细]

  • 文章目录一.Spark性能优化概述二.运行环境优化2.1数据本地性2.2数据存储格式三.RDD算子优化3.1尽可能复用同一个RDD3.2对多次使用的RDD进行持久化四.参数微调五.数据倾斜六.Spark常用的调优参数6.1在内存中缓存数据6... [详细]

  • 1、测试环境的鉴定我们需要确定软件应用程序的物理测试和生产环境。还需要确定测试团队用到的工具和资源。这里的环境、工具和资源指的是硬件、软件和网络的配置和设置。全面了解测试环境可以更好的规划和设计本次测试。同时测试过程中也需要定期审核环... [详细]

  • PostgreSQL汉字拼音首字母,最近有个需求要做搜索优化,要求提取汉字首字母识别输入,图方便直接数据库用函数批量转换了,整理了网上的两个方法函数备忘,非原创。_pgsql汉字拼音pgsql汉字拼音PostgreSQL汉字拼音首字... [详细]

  • docker应用;docker自定义网络;网络连接Docker应用-自定义网络连接Docker网络文章目录Docker网络网络的基础配置自定义网络网络连通网络的基础配置大量的互联网应用服务包括多个服务组件,这往往需要多个容器之间通过网络通信... [详细]

  • web端操作下载ssl证书断点续传页面展示修改模拟器连接模拟器下载ssl证书1.设置,进入options2.选择https模块,全部选项勾选,点击Actions选择trusrRootCertificate断点续传1.打开浏览器输入内容2.选... [详细]

  • JavaCatchingandHandlingExceptionsJavaCatchingandHandlingExceptions一、CatchingandHandlingExceptions本节描述如何使用三个异常处理程序组件(try、... [详细]

  • 1、我们的目的是讲解“跳转语句”的区别2、先把c++中包含的几个语句先总结概括一下几种典型的c++语句:①空语句+语句块;②条件语句(if,switch);③迭代语句(while,do-while,for,范围for);④跳转语句(brea... [详细]

  • 第一次通过Tensorflow对象检测API了解对象检测。它很容易使用。传入了一张海滩的图片,作为回报,API在它识别的对象上绘制了方框。这似乎很神奇。很好奇,想剖析API,了解它到底是如何在幕后工作的。这很难,我失败了。Tensorflo... [详细]

  • 图像分割过程中,图像被分解成若干互不重叠区域,这些区域通常对应于实际场景中各种物体或图像特定部分。:在遥感应用中,图像分割用于处理来自卫星或航空摄影图像,以识别地表特征,如土地覆盖、水体、林地等,对环境监测、城市规划和农业管理等领... [详细]

  • 兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行,即是通常说的软件的可移植性。兼容的类型,如果细分的话,有平台兼容,网络兼容,数据库兼容,以及数据格式的兼容。兼容测试的重点是,对兼容环境的分析。通常,是在运行软件的环境不... [详细]

相关标签
  

闽ICP备14008679号