关于修复弹窗被360弹窗拦截器拦截的问题的解决案例的分享

本文介绍了修复编码器被360弹窗拦截器拦截的问题,通过分析Windows消息和使用WPF的HwndSource进行消息拦截。在找到主要拦截消息WM_SHOWWINDOW和WM_CLOSE后,通过在WM_CLOSE中处理显示窗体的消息,成功解决了问题。

一、查找问题

收到反馈说编码器被360弹窗拦截器拦截,经测试发现强力模式下也并没有直接拦截,但是会出现提示框;猜测有可能是用户不小心添加过滤了或者其他版本会有拦截,导致编码器被关闭无法正确编码。查找资源后发现,弹窗拦截是通过发送Windows消息触发隐藏和关闭的。

于是考虑先把编码器生成后接受到的消息打印出来查看分析。

由于WPF本身是有对消息和窗口句柄等进行封装的,所以需要重新去添加using System.Windows.Interop; 这个namespace中所包含的东西主要是为 Windows Presentation Foundation (WPF) 和其他技术(如 Win32API)之间的互操作提供支持类型,并为涉及 WPF 的其他特定互操作方案提供基类。在WPF中使用WindowProc,首先要获得一个HWND句柄(一个IntPtr类型),然后通过创建一个HwndSource对象,再通过调用这个对象中的AddHook方法来添加WindowProc。其中HwndSource实现包含 WPF 内容的 Win32 窗口。WPF 内容在此窗口中排列、度量、呈现,并且可交互式输入。HwndSource 类设计用于一般的交互操作,而不是设计用作托管 HWND 包装。通常,它不会提供操作窗口的托管方法或检测其状态的属性。相反,HwndSource类提供通过 Handle 属性对 Win32 窗口句柄 (HWND) 的访问,可通过 PInvoke 技术将其传递到 Win32 APIs 以操作该窗口。

现在开始进行挂钩,可以通过添加SourceInitialized的事件处理函数引发添加,直接重载OnSourceInitialized函数来添加。下面是通过添加处理函数的方式实现。
在这里插入图片描述
此外也有两种获取HwndSource的方法
在这里插入图片描述
上面为将窗口作为互操作方案的源生成HwndSource。
在这里插入图片描述
下面则通过WindowInteropHelper获取窗口句柄,通过句柄来生成。然后通过挂钩上消息处理函数自定义的WndProc。对于WinForm可以直接重载WndProc函数protected override void WndProc(ref Message m) 然后在窗体显示时Shown添加过滤即可。WPF中再添加窗口内容呈现的处理函数进行过滤把窗口创建呈现之后产生的消息打印到桌面。
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)前四个参数跟MSG结构体的意义一致,最后一个handled则代表这个消息是否告诉系统已经处理结束,是否需要继续放行传递让其他的方法执行。
在这里插入图片描述
大致生成了如下消息,通过拦截与不拦截、生成窗口后再添加拦截等测试,经分析,主要是自定义消息49642以及
WM_SHOWWINDOW = 24 (0x0018)当隐藏或显示窗口是发送此消息给这个窗口
WM_CLOSE = 16(0x0010) 当一个窗口或应用程序要关闭时发送一个信号的问题。
在这里插入图片描述

二、验证方法

经过对已拦截的消息的分析,先对已知的消息进行相关测试。

  1. 既然获取到了WM_SHOWWINDOW(wParam = 0x000000)隐藏窗口以及WM_CLOSE,能否直接拦截过滤掉,把handled设置为True告诉系统已经处理过。
    在这里插入图片描述
    结果:
    能够正常编码生成文件,但是窗口消失。
  2. 既然无法直接通知系统已关闭,能否收到隐藏窗体时,直接调用ShowWindow的方法直接把窗体显示。
    在这里插入图片描述
    结果:
    无论是否更改handled的值告诉系统或者更改显示窗体的方法,都无法在收到隐藏窗体消息的时候发出显示窗体的消息重新显示窗体。
  3. 由于无法在收到隐藏窗体消息的时候直接显示窗体,所以需要查找出错的环节,首先验证在窗体被隐藏后能否通过发送消息显示出来。
    结果:
    通过外部程序发送显示的消息WM_SHOWWINDOW(wParam = 0x000001)能够正常显示;
    编辑此区域
    接下来验证是否是所调用的方法出现错误,把该函数以及参数新建到一个控制台程序在窗体隐藏时运行。
Win32.ShowWindow(hwnd, Win32.SW_SHOW);(在Win32中定义如下)
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
//ShowWindow参数
public const int SW_SHOW = 1;

结果:
经测试发现可以把窗体唤醒显示。因此初步判断异常出现在接收到隐藏窗体消息时无法正确显示。
4. 在WM_SHOWWINDOW(wParam = 0x000000)的执行过程中添加LogHelper记录,通过对比相关消息发现,确实有进入执行该步骤,但却无法显示窗体,推测窗体处于要隐藏但尚未隐藏的状态,即收到要隐藏的消息,但窗体的wParam还是等于1的,而且在WM_SHOWWINDOW(wParam = 0x000000)这个消息的处理中发出WM_SHOWWINDOW(wParam = 0x000001)消息有被微软本身做出相关处理,不执行。
在这里插入图片描述

  1. 验证在WM_SHOWWINDOW(wParam = 0x000000)消息之后发出显示窗体的消息能否把窗体显示,即在WM_CLOSE中处理。
    在这里插入图片描述
    结果:
    能够正确在360弹窗拦截器隐藏窗口发出关闭消息后马上显示窗体,拦截次数从9次变成10次并且不会被再次隐藏。
    此外,在使用外部软件显示窗体时,会被拦截器再次拦截,故把handled值改为False测试,发现在显示之后还是会被拦截,推测是360弹窗拦截器有对消息做重复检测,但通过handled=True告诉系统已经处理过,让弹窗拦截器无法截获该消息,认为窗体已经正确关闭。至此,已经解决360弹窗拦截的问题,以上就是我对修复该问题的分析流程。
严格拦截任何网站的所有弹窗请求 弹出式窗口拦截器(strict)是一个轻量级的扩展,用于防止网站打开弹出式窗口(而其他弹出式窗口拦截器则是这种扩展在创建之后不会阻止弹出窗口,但是一旦请求被阻止)。该扩展暂停了用户关注的各种窗口打开请求。您可以接受或拒绝请求。数组中显示了多个唯一的请求。如果网站多次请求单个网址,则会显示一个徽章编号,指出对此特定网址的请求总数。 请注意,扩展名最近从“弹出窗口阻止程序(最终)”更名为“弹出窗口阻止程序(严格)” 选项: 1.拒绝弹出请求 2.允许弹出请求 3.在后台选项卡中打开弹出式请求 4.将当前页面重定向到弹出的URL源 支持的阻止方法: 1. window.open 2. a-> target = _blank 有关错误报告,请转到: https://github.com/schomery/popup-blocker/issues 有关常见问题,请转到: http://add0n.com/popup-blocker.html 为了测试你当前的弹出窗口阻止程序的有效性, http://tools.add0n.com/popup-blocker.html --- 您现在可以将Popup Blocker(严格)翻译成您的语言; https://www.transifex.com/github-7/popup-blocker-strict/ --- 更改日志: 版本0.2.8: 1.如果鼠标悬停在弹出通知上,则计数器停止计数,以便用户可以查看弹出请求 2.将鼠标悬停在弹出窗口中,也会在工具提示中显示请求的URL 3.一些内部代码错误修复应用。 版本0.3.0: 1.现在可以通过右键单击工具栏按钮来允许或拒绝上一个操作 2.如果选中选项,弹出窗口阻止程序将执行预定义的操作,而不显示通知面板。 版本0.3.8: `。解决了一个问题:WordPress的编辑器没有对齐文本。 支持语言:Deutsch,English,Français,Türkçe,español,português (Brasil),svenska,中文 (简体),한국어
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值