Search code examples
pythonpython-3.xpywinauto

Pywinauto unable to find/close pop-up window


Source code

def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

if is_admin():
    app = Application(backend='uia').start("C:\\Program Files (x86)\\Advantech\\AdamApax.NET Utility\\Program\\AdamNET.exe")
    win = app['Advantech Adam/Apax .NET Utility (Win32) Version 2.05.11 (B19)']
    win.wait('ready')
    win.menu_select("Setup->Refresh Serial and Ethernet")
    win.top_window().print_control_identifiers(filename="file.txt")
    # win.top_window().OKButton.click_input()  ---------This is what I hope to do

else
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)

Problem Statement

I had to run this application with elevation rights. The above is my code. The problem is I can't identify the window (view in output image) that pops up after selection from menu. I need to close the window. Please excuse the line

win.top_window().print_control_identifiers(filename="file.txt")

It was meant write the identifiers into a text file because the structure of this code does not display the outputs for me to view. However, since nothing is appended, I guess pywinauto couldn't identify the dialog.

For a clearer understanding, please view the image (input) of when it selects the menu.

Input

Now, it pops up with this dialog (output)

Output

I've also used spy to identify the caption and it gives:

(Handle: 004E07D4, Caption: Information, Class: #32770(Dialog), Style: 94C801C5)

Other things I've tried:

Besides using win.topwindow() to identify the dialog, I've used

win[Information].OKButton.click_input()
win[Information].OK.click_input()
win[Information].OK.close()
win[Information].OK.kill(soft=false)
win.Information.OKButton.click_input()
win.Information.OK.click_input()
win.Information.OK.close()
win.Information.OK.kill(soft=false)
app[Information] ...... curious if I could discover the new window from original application

I've also send keys like enter, space, esc & alt-f4 to close the dialog with libraries like keyboard, pynput & ctypes. It still doesn't work.

Link to download the same application: http://downloadt.advantech.com/download/downloadsr.aspx?File_Id=1-1NHAMZX

Any help would be greatly appreciated !


Solution

  • I finally found a thread that demonstrated the way multi thread works to solve this issue. I tried it myself and it works. It's a little different as a few parts of the code have depreciated. Here is the link to the solution: How to stop a warning dialog from halting execution of a Python program that's controlling it?

    Here are the edits I made to solve the problem:

    def is_admin():
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False
    
    if is_admin():
    
        def __init__(self, window_name, quit_event):
            threading.Thread.__init__(self)
            self.quit_event = quit_event
            self.window_name = window_name
    
        def run(self):
            while True:
                try:
                    handles = windows.find_windows(title=self.window_name)
                except windows.WindowNotFoundError:
                    pass 
                else: 
                    for hwnd in handles:
                        app = Application()
                        app.connect(handle=hwnd)
                        popup = app[self.window_name]
                        popup.close()
                if self.quit_event.is_set():
                    break
                time.sleep(1) 
    
        quit_event = threading.Event()
        mythread = ClearPopupThread('Information', quit_event)
        mythread.start()
        application = Application(backend="uia").start("C:\\Program Files (x86)\\Advantech\\AdamApax.NET Utility\\Program\\AdamNET.exe")
        time.sleep(2)
        win = application['Advantech Adam/Apax .NET Utility (Win32) Version 2.05.11 (B19)']
        win.menu_select("Setup->Refresh Serial and Ethernet")
        quit_event.set()
    
    else:
        ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
    

    The best thing is this solution works for every other dialog that halts the main script from working & I could use them to do different actions like clicking buttons, inserting values, by adding more multi threads.