首页 技术 正文
技术 2022年11月10日
0 收藏 986 点赞 3,453 浏览 2631 个字

需求:

在实际场景中会有自身程序在调用第三方的动态库过程中,因为第三方的动态库弹框导致线程阻塞,必须手动将弹窗关闭后才能回到自身程序的主线程中。

最简单的场景就是很多自助设备,本身是没有固定操作员的,如果用户在看到弹框后没有手动点击关闭则弹框会一直会存在。

解决方案:

1、通过Windows提供的API,FindWindow(通过Window的Title)获取到第三方弹框句柄,通过SendMessage向Winwos发起关闭该句柄的命令;

2、如果该弹框有“关闭“按钮,则通过FindWindow获取到句柄后,再通过FindwWindowEx找到“关闭”按钮子句柄,然后通过SendMessage发起鼠标左击事件;

Code:

方案1:

   /// <summary>
/// 寻找系统的全部窗口
/// </summary>
/// <returns></returns>
public WindowInfo[] GetAllDesktopWindows()
{
List<WindowInfo> wndList = new List<WindowInfo>();
EnumWindows(delegate (IntPtr hWnd, int lParam)
{
WindowInfo wnd = new WindowInfo();
StringBuilder sb = new StringBuilder(256);
//get hwnd
wnd.hWnd = hWnd;
//get window name
GetWindowTextW(hWnd, sb, sb.Capacity);
wnd.szWindowName = sb.ToString();
//get window class
GetClassNameW(hWnd, sb, sb.Capacity);
wnd.szClassName = sb.ToString();
//add it into list
wndList.Add(wnd);
return true;
}, 0);
return wndList.ToArray();
}/// <summary>
/// 根据指定窗口标题暴力干掉这个窗口
/// </summary>
/// <param name="windowTitle">window的标题</param>
/// <param name="second">指定多少秒后关闭window</param>
/// <returns></returns>
public async Task KillWindow(string windowTitle, int second = 3)
{
try
{
await Task.Delay(TimeSpan.FromSeconds(second));
#region 通过获取所有窗口方式关闭 WindowInfo[] a = GetAllDesktopWindows();
int i = 0;
int index = 0;
for (i = 0; i < a.Length; i++)
{
if (a[i].szWindowName.ToString().Contains(windowTitle))
{
index = i;
IntPtr myIntPtr = a[index].hWnd;
//先置顶!!!不置顶发送windows消息没卵用
SetWindowPos(myIntPtr, -1, 0, 0, 0, 0, 1 | 2);
if (myIntPtr != null)
{
IntPtr childHwnd = FindWindowEx(myIntPtr, IntPtr.Zero, null, "否(&N)");
SendMessage(childHwnd, BM_CLICK, 0, 0); //发送点击按钮的消息
}
break;
}
}
#endregion
}
catch (Exception)
{
}
}

  方案二:

   /// <summary>
/// 根据指定窗口标题暴力干掉这个窗口
/// </summary>
/// <param name="windowTitle">window的标题</param>
/// <param name="second">指定多少秒后关闭window</param>
/// <returns></returns>
public async Task KillWindowAndBtn(string windowTitle, int second = 3, string btnTxt = "否(&N)")
{
try
{
await Task.Delay(TimeSpan.FromSeconds(second));
#region 通过获取所有窗口方式关闭 WindowInfo[] a = GetAllDesktopWindows();
int i = 0;
int index = 0;
for (i = 0; i < a.Length; i++)
{
if (a[i].szWindowName.ToString().Contains(windowTitle))
{
index = i;
IntPtr myIntPtr = a[index].hWnd;
//先置顶!!!不置顶发送windows消息没卵用
SetWindowPos(myIntPtr, -1, 0, 0, 0, 0, 1 | 2);
if (myIntPtr != null)
{
IntPtr childHwnd = FindWindowEx(myIntPtr, IntPtr.Zero, null, btnTxt);
SendMessage(childHwnd, BM_CLICK, 0, 0); //发送点击按钮的消息
}
break;
}
}
#endregion
}
catch (Exception)
{
}
}

  调用方式(第一种方案):

        private async void KillCardErrorWindow()
{
WinUtils utils = new WinUtils();
//通过获取全部窗口方式进行模糊查询
await utils.KillWindow("卡");
}

  

调用第二种方案:

  /// <summary>
/// 杀掉医保读卡dll生成的window
/// </summary>
private async void KillPassWordWindow()
{
WinUtils utils = new WinUtils();
//通过获取全部窗口方式进行模糊查询
await utils.KillWindow("输入密码"); //"读市民卡错误提示:"
}

PS: 无论使用哪一种方案,都必须在调用第三方API之前先发起杀掉window的方法,留意代码即可知道,都是通过异步执行的。

所以结合实际场景需要,请先设定Task.Delay的时间值。


    					
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,024
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,514
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,362
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,143
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,776
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,854