def show(): from __future__ import print_function from pywinauto import Application # Open "Control Panel" Application().start('control.exe') app = Application(backend='uia').connect(path='explorer.exe', title='Control Panel') # Go to "Programs" app.window(title='Control Panel').ProgramsHyperlink.invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) # Go to "Installed Updates" app.window(title='Programs').child_window( title='View installed updates', control_type='Hyperlink').invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) list_box = app.InstalledUpdates.FolderViewListBox # list all updates items = list_box.descendants(control_type='ListItem') all_updates = [item.window_text() for item in items] print('\nAll updates ({}):\n'.format(len(all_updates))) print(all_updates) # list updates from "Microsoft Windows" group only windows_group_box = list_box.child_window(title_re='^Microsoft Windows.*', control_type='Group') windows_items = windows_group_box.descendants(control_type='ListItem') windows_updates = [item.window_text() for item in windows_items] print('\nWindows updates only ({}):\n'.format(len(windows_updates))) print(windows_updates)
import os import json import helper from pywinauto import Application localappdata = os.getenv('APPDATA') # All VPN job goes here with open("config.json") as configfile: conf = json.load(configfile) login, password = helper.main_worker(conf) # Starting OpenVPN service # Probably something bad happens there # (single thread, not setting up connection properly) subprocess.call(["run_ovpn.bat"]) # Starting Spotify application @ C:\Users\%Username%\AppData\Roaming\Spotify # Change username here app = Application(backend="uia").start(localappdata + r"\Spotify\Spotify.exe") app.wait_cpu_usage_lower() # Unimportant method. Should be removed app.Spotify.print_control_identifiers() # Login field app.Spotify.edit2.set_text(login) # Password field app.Spotify.edit4.set_text(password) # Submit button app.Spotify.Button5.click()
class RealBandController: """An object for controlling RealBand.""" _TARGET_VERSION = '2018.0.2.5' def __init__(self, binary_path=r'C:\RealBand\RealBand.exe', try_connect=True): self.realband_version = _get_exe_version(binary_path) if self.realband_version != self._TARGET_VERSION: print('This code was written for RealBand {}, your version is {}. ' 'Proceed with caution.' .format(self._TARGET_VERSION, self.realband_version), file=sys.stderr) self._app = Application(backend='win32') if try_connect: try: self._app.connect(path=binary_path) except ProcessNotFoundError: try_connect = False if not try_connect: self._app.start(binary_path) self._app.wait_cpu_usage_lower(threshold=5) def get_ready(): rb_window = self._app.window(class_name='RealBand') if rb_window.exists() and rb_window.is_visible() and rb_window.is_enabled(): return # Reject attempts to recover from a crash dialog = self._app.window(class_name='#32770') dialog_text = dialog.StaticWrapper2.element_info.name if ('Okay to restore all the default settings' in dialog_text or 'Recover data from last session' in dialog_text): dialog.Button2.click() raise TimeoutError() wait_until_passes(func=get_ready, exceptions=(ElementNotFoundError, TimeoutError), timeout=15, retry_interval=1) self._song_pane = self._app.RealBand.children( class_name='TPanelWithCanvas')[10] @property def app(self): return self._app def kill(self): self._app.kill() for proc in psutil.process_iter(): if proc.name() in ['bbw2.exe', 'RealBand.exe']: print('Killing', proc, file=sys.stderr) try: proc.kill() except psutil.NoSuchProcess: traceback.print_exc(file=sys.stderr) def load_song(self, path): """Load a song from the given file.""" self._menu_select('File->Open') self._open_file(path) try: # Get the annoying Comments window out of the way self._app.Comments.minimize() except MatchError: pass def load_style(self, path): """Load a style from the given file.""" self.wait_ready() def open_dialog(): # Bring up the style popup menu and choose to open a style file self._song_pane.click_input(coords=(44, 73), absolute=False) menu = self._app.window(class_name='#32768') menu.menu_item('File Open Style').click_input() wait_until_passes(func=open_dialog, exceptions=ElementNotFoundError, timeout=120, retry_interval=0.4) self._open_file(path) def _open_file(self, path): """Input a path in the file open dialog.""" path = os.path.normpath(os.path.abspath(path)) while True: dialog = self._app.window(class_name='#32770') dialog.wait('ready') # If asked whether to save changes, say no try: dialog_text = dialog.StaticWrapper2.element_info.name if 'Save it?' in dialog_text: dialog.Button2.click() continue except MatchError: pass break dialog.Edit1.set_edit_text(path) dialog.Edit1.send_keystrokes('{ENTER}') self.wait_ready(timeout=60) def save_song(self, path, filetype='MIDI File (.MID) (*.MID)'): """Save the current song under the given filename.""" path = os.path.normpath(os.path.abspath(path)) self._menu_select('File->Save As') file_dialog = self._app.window(class_name='#32770') file_dialog.wait('ready') file_dialog.ComboBox2.select(filetype) file_dialog.Edit1.set_edit_text(path) file_dialog.Edit1.send_keystrokes('{ENTER}') self.wait_ready() def generate_all(self): """Generate all Band-in-a-Box tracks.""" self._menu_select('Generate->Generate All BB Tracks') self.wait_ready() def set_key(self, key, transpose=False): """Set the key of the song.""" if transpose: raise NotImplementedError('transpose not implemented') self._menu_select('Edit->Key Signature') key_dialog = self._app.window(class_name='TKEY') key_dialog.wait('ready') key_dialog.TComboBox1.select(key) key_dialog.TRadioButton4.click() # No Transpose key_dialog.TButton3.click() # OK self.wait_ready() @property def key_signature(self): """The key signature of the song.""" text = self._get_menu_item_text('Edit->Key Signature') return re.search(r'\[([A-G].?)\]$', text).group(1) @property def time_signature(self): """The time signature (meter) of the song.""" text = self._get_menu_item_text('Edit->Meter (Time Signature)') return re.search(r'\[([0-9]+/[0-9]+)\]$', text).group(1) @property def tempo(self): """The tempo of the song.""" text = self._get_menu_item_text('Edit->Tempo') return float(re.search(r'\[([0-9.,]+)\]$', text).group(1)) def _get_menu_item_text(self, path, timeout=10, retry_interval=0.5): def get_text(): return self._app.RealBand.menu_item(path).text() return wait_until_passes(func=get_text, exceptions=(ElementNotEnabled, RuntimeError), timeout=timeout, retry_interval=retry_interval) def _menu_select(self, path, timeout=10, retry_interval=0.5): self.wait_ready() def select_option(): self._app.RealBand.menu_select(path) wait_until_passes(func=select_option, exceptions=(ElementNotEnabled, RuntimeError), timeout=timeout, retry_interval=retry_interval) def wait_ready(self, timeout=30): self._app.RealBand.wait('ready', timeout=timeout)
- pywinauto 0.6.1+ This example opens "Control Panel", navigates to "Installed Updates" page and lists all updates (for all apps) as well as OS Windows updates only. """ from __future__ import print_function from pywinauto import Application # Open "Control Panel" Application().start('control.exe') app = Application(backend='uia').connect(path='explorer.exe', title='Control Panel') # Go to "Programs" app.window(title='Control Panel').ProgramsHyperlink.invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) # Go to "Installed Updates" app.window(title='Programs').child_window(title='View installed updates', control_type='Hyperlink').invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) list_box = app.InstalledUpdates.FolderViewListBox # list all updates items = list_box.descendants(control_type='ListItem') all_updates = [item.window_text() for item in items] print('\nAll updates ({}):\n'.format(len(all_updates))) print(all_updates) # list updates from "Microsoft Windows" group only windows_group_box = list_box.child_window(title_re='^Microsoft Windows.*', control_type='Group')
ClickSystemTrayIcon(button) RightClickSystemTrayIcon(button) """Often, when you click/right click on an icon, you get a popup menu. The thing to remember at this point is that the popup menu is a part of the application being automated not part of explorer.""" # connect to outlook outlook = Application.connect(path='outlook.exe') # click on Outlook's icon taskbar.ClickSystemTrayIcon("Microsoft Outlook") # Select an item in the popup menu outlook.PopupMenu.Menu().get_menu_path("Cancel Server Request")[0].click() app.wait_cpu_usage_lower(threshold=5) # wait until CPU usage is lower than 5% # call ensure_text_changed(ctrl) every 2 sec until it's passed or timeout (4 sec) is expired @always_wait_until_passes(4, 2) def ensure_text_changed(ctrl): if previous_text == ctrl.window_text(): raise ValueError( 'The ctrl text remains the same while change is expected') """ Cross-platform module to emulate mouse events like a real user pywinauto.mouse.click(button='left', coords=(0, 0))
class BandInABoxController: """An object for controlling Band-in-a-Box.""" _TARGET_VERSION = '2018.0.0.520' def __init__(self, binary_path=r'C:\bb\bbw.exe', try_connect=True): self.biab_version = _get_exe_version(binary_path) if self.biab_version != self._TARGET_VERSION: print('This code was written for Band-in-a-Box {}, your version is {}. ' 'Proceed with caution.' .format(self._TARGET_VERSION, self.biab_version), file=sys.stderr) self._app = Application(backend='win32') if try_connect: try: self._app.connect(path=binary_path) except ProcessNotFoundError: try_connect = False if not try_connect: self._app.start(binary_path) self._app.wait_cpu_usage_lower(threshold=5) def get_ready(): rb_window = self._app.window(class_name='TBandWindow') if rb_window.exists() and rb_window.is_visible() and rb_window.is_enabled(): return raise TimeoutError() wait_until_passes(func=get_ready, exceptions=(ElementNotFoundError, TimeoutError), timeout=15, retry_interval=1) @property def app(self): return self._app def kill(self): self._app.kill() for proc in psutil.process_iter(): if proc.name() == 'bbw.exe': print('Killing', proc, file=sys.stderr) try: proc.kill() except psutil.NoSuchProcess: traceback.print_exc(file=sys.stderr) def load_song(self, path): """Load a song from the given file.""" self.menu_select('File->Open') self._open_file(path) def _open_file(self, path): """Input a path in the file open dialog.""" while True: dialog = self._app.window(class_name='#32770') dialog.wait('ready') # If asked whether to save changes, say no try: dialog_text = dialog.StaticWrapper2.element_info.name if 'Save it?' in dialog_text: dialog.Button2.click() continue except MatchError: pass break dialog.Edit1.set_edit_text(path) dialog.Edit1.send_keystrokes('{ENTER}') self._wait_ready(timeout=60) def save_song(self, path): """Save the current song under the given filename.""" self.menu_select('File->Save song As') file_dialog = self._app.window(class_name='#32770') file_dialog.wait('ready') file_dialog.Edit1.set_edit_text(path) file_dialog.Edit1.send_keystrokes('{ENTER}') self._wait_ready() def menu_select(self, path, timeout=10, retry_interval=0.5): self._wait_ready() def select_option(): self._app.TBandWindow.menu_select(path) wait_until_passes(func=select_option, exceptions=(ElementNotEnabled, RuntimeError), timeout=timeout, retry_interval=retry_interval) def _wait_ready(self, timeout=30): self._app.TBandWindow.wait('ready', timeout=timeout)
This example opens "Control Panel", navigates to "Installed Updates" page and lists all updates (for all apps) as well as OS Windows updates only. """ from __future__ import print_function from pywinauto import Application # Open "Control Panel" Application().start('control.exe') app = Application(backend='uia').connect(path='explorer.exe', title='Control Panel') # Go to "Programs" app.window(title='Control Panel').ProgramsHyperlink.invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) # Go to "Installed Updates" app.window(title='Programs').child_window(title='View installed updates', control_type='Hyperlink').invoke() app.wait_cpu_usage_lower(threshold=0.5, timeout=30, usage_interval=1.0) list_box = app.InstalledUpdates.FolderViewListBox # list all updates items = list_box.descendants(control_type='ListItem') all_updates = [item.window_text() for item in items] print('\nAll updates ({}):\n'.format(len(all_updates))) print(all_updates) # list updates from "Microsoft Windows" group only