Search code examples
pythonpywinauto

GUI Automation of policy change for logoff button. pywinauto.findwindows.ElementNotFoundError: error. How to switch context?


enter image description here

I am automating the steps to change the policy for the logoff button. The steps involved are:

  1. Open Local Group Policy using gpedit.msc

  2. Select "Start Menu and Taskbar" from the dropdown in User Configuration > Administrative Template from the left pane

  3. In the right pane, double click on "Change Start Menu power button"

  4. Select the radio button "Enabled"

  5. From the dropdown menu of options: Select "Log Off"

I have gotten through the third step, but I have a problem in mapping the "Change Start Menu Power Button" from the second step. My code is as below:

from pywinauto import Application

Application().start(r'mmc gpedit.msc') 
app = Application(backend="uia").connect(path='mmc.exe')
#app.LocalGroupPolicyEditor.dump_tree()

Admin_template = app.LocalGroupPolicyEditor.child_window(title="User 
Configuration", control_type="TreeItem").child_window(title="Administrative 
Templates", control_type="TreeItem") # since there are same templates 
Admin_template.double_click_input() # it expands the subtree
#Admin_template.dump_tree()

Start_menu = Admin_template.child_window(title="Start Menu and Taskbar", 
control_type="TreeItem").double_click_input()
Start_menu.dump_tree()
#Admin_template.child_window(title="Start Menu and Taskbar", 
control_type="TreeItem").dump_tree()

#Change_start_menu = Start_menu.child_window(title="Change Start Menu power 
#button", control_type="MenuItem").double_click_input()
#Change_start_menu.dump_tree()

I have trouble in finding and mapping the elements in the right pane. Also, when I use Start_menu.dump_tree(), there are only "Notification" elements shown. However, the rest, which includes "Change Start Menu power button," is what I'll be double clicking next.

enter image description here

I appreciate the help. Thanks.


Solution

  • It was kinda tricky, but this should do the job (it does all the steps you've listed - presses OK - and closes the program):

    import pywinauto
    
    pywinauto.Application().start(r'mmc gpedit.msc') 
    app = pywinauto.Application(backend="uia").connect(path='mmc.exe')
    
    admin_template = app.LocalGroupPolicyEditor.child_window(title="User Configuration", control_type="TreeItem").child_window(title="Administrative Templates", control_type="TreeItem")
    admin_template.double_click_input()
    
    start_menu = admin_template.child_window(title="Start Menu and Taskbar", control_type="TreeItem")
    start_menu.double_click_input()
    
    option_list = app.LocalGroupPolicyEditor.child_window(auto_id="12786", control_type="List")
    
    # Just select any of the first options to change the focus to the list.
    first_elem = option_list.child_window(title="Add Search Internet link to Start Menu", control_type="ListItem")
    first_elem.click_input()
    
    # Used to scroll down the window so that the wanted option becomes visible.
    pywinauto.keyboard.send_keys("cccc")
    
    option = option_list.child_window(title="Change Start Menu power button", control_type="ListItem")
    option.double_click_input()
    
    pop_up = app.LocalGroupPolicyEditor.child_window(auto_id="tableLayoutFullForm", control_type="Pane")
    
    radio = pop_up.child_window(title="Enabled", auto_id="radioButtonEnabled", control_type="RadioButton")
    radio.click_input()
    
    drop_down = pop_up.child_window(title="Choose one of the following actions", auto_id="dropDownListChoose one of the following actions", control_type="ComboBox")
    drop_down.click_input()
    
    # 'Hack' to first select the Restart option and then the next option after that which starts with l (=Log off).
    # This ensures that the correct setting gets set despite of what the setting was before.
    pywinauto.keyboard.send_keys("rl{ENTER}")
    
    ok = pop_up.child_window(title="OK", auto_id="buttonOK", control_type="Button")
    ok.click_input()
    
    app.kill()
    

    Make sure to run this script as administrator or else it will fail.

    Feel free to ask if you got any questions about the code :)

     

    Edit:

    If you're running a version of pywinauto <0.6.0, you'll have to replace the two occurances (lines 19 and 34) of pywinauto.keyboard.send_keys() with:

    pywinauto.SendKeysCtypes.SendKeys()
    

    If that doesn't work you could try:

    pywinauto.keyboard.SendKeys()