need:
In the actual scene, there will be its own program in the process of calling the third-party dynamic library, because the third-party dynamic library pop-up box causes the thread to block, and the pop-up window must be closed manually before returning to the main thread of the own program.
The simplest scenario is that many self-service devices do not have fixed operators. If the user does not manually click to close the pop-up box after seeing it, the pop-up box will always exist.
solution:
1. Through the API provided by Windows, FindWindow (through the Title of Window) obtains the handle of the third-party pop-up box, and initiates a command to close the handle to Winwos through SendMessage;
2. If the pop-up box has a "Close" button, after obtaining the handle through FindWindow, find the "Close" button sub-handle through FindwWindowEx, and then initiate a left-click event through SendMessage;
Code:
plan 1:
/// <summary> /// Find all windows of the system /// </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> /// Violently kill the window according to the specified window title /// </summary> /// <param name="windowTitle">window title</param> /// <param name="second">Specify how many seconds to close the window</param> /// <returns></returns> public async Task KillWindow(string windowTitle, int second = 3) { try { await Task.Delay(TimeSpan.FromSeconds(second)); #region is closed by getting all windows 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; // Top first! ! ! It is useless to send windows messages without sticking to the top 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); //Send the message of the button click } break; } } #endregion } catch (Exception) { } }
Option II:
/// <summary> /// Violently kill the window according to the specified window title /// </summary> /// <param name="windowTitle">window title</param> /// <param name="second">Specify how many seconds to close the window</param> /// <returns></returns> public async Task KillWindowAndBtn(string windowTitle, int second = 3, string btnTxt = "否(&N)") { try { await Task.Delay(TimeSpan.FromSeconds(second)); #region is closed by getting all windows 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; // Top first! ! ! It is useless to send windows messages without sticking to the top 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); //Send the message of the button click } break; } } #endregion } catch (Exception) { } }
Calling method (the first scheme):
private async void KillCardErrorWindow() { WinUtils utils = new WinUtils(); //Fuzzy query by getting all windows await utils.KillWindow("卡"); }
Call the second scheme:
/// <summary> /// Kill the window generated by the medical insurance card reader dll /// </summary> private async void KillPassWordWindow() { WinUtils utils = new WinUtils(); // Fuzzy query by getting all windows await utils.KillWindow( " Enter password " ); // "Error reading citizen card:" }
PS: No matter which solution is used, the method of killing the window must be initiated before calling the third-party API. Pay attention to the code to know that it is executed asynchronously.
Therefore, according to the actual scene needs, please set the time value of Task.Delay first.