robocorp-windows

Quickstart

Getting started with robocorp.windows is as simple as:

windows.desktop().windows_run("notepad.exe") # starts Notepad with Windows Run notepad = windows.find_window('subname:"Notepad"') # controls & gets the window into focus notepad.find('control:"MenuItemControl" and name:"File"').click() # clicks the found "File" menu item notepad.close_window() # closes the current window

Now, if we put this in a Task/Action Package, we could save a tasks.py file with the following content:

from robocorp import windows from robocorp.tasks import task desktop = windows.desktop() @task def automate_notepad(): """Automates the Notepad app by clicking the 'File' menu item, then exits.""" desktop.windows_run("notepad.exe") notepad = windows.find_window('subname:"Notepad"') try: notepad.find('control:"MenuItemControl" and name:"File"').click() finally: notepad.close_window()

Locators

One of the key concepts in the library are locators. A locator is a string which identifies how to reach a given element to interact with. This string can have multiple entries separated by spaces such as:

<property_name>:"<property value>" <property_name>:"<property value>"

Note: if the <property value> itself doesn't have spaces the " is not needed.

It's also possible to consider the parent/child hierarchy so that multiple matches are done when using >. Example: name:Calculator > class:TextBlock.

Also, it's possible to use or constructs to create more advanced matches. Example: (name:0 or name:Zero) and class:Button. Note: > must always be top-level and may not appear inside an or.

The property names available for matching are:

  • name: identifies a target window/control by its name. Example: name:"My Window".

  • regex: identifies a target window/control by its name matching using a regexp. Example: regex:".*Calc.*".

  • subname identifies a target window/control by its name matching using the in operator. Example: subname:cal".

  • class: identifies a target window/control by its class. Example: class:Button, class:TextBlock.

  • control (may also be used as type): identifies a target window/control by its type. Example: control:ButtonControl, type:ButtonControl.

  • id (may also be used as automationid): identifies a target window/control by its automation id. Example: id:"open button".

  • executable: identifies a target window by its executable name (may be the full path or just basename). Example: executable:notepad.exe)

  • handle: the target window handle. Example: handle:21345.

  • path: identifies a target element by its index-based path traversal from the parent. Example path:2|3|8|2.

  • depth: identifies a target element by its depth from the parent. Example depth:2.

It's also possible to get an element and then go deeper in the structure to have the same result.

i.e.: Using:

from robocorp import windows windows.find_window('name:Calculator').find('path:2|3|1').click()

is the same as:

from robocorp import windows windows.find_window('name:Calculator').find('path:2 > path:3|1').click()

In general the recommended approach is getting the top-level window of interest with windows.find_window and then getting sub-elements as needed (and if multiple elements have the same parent, first finding the parent and then getting children elements from that parent for faster access).

Note: when querying the information, APIs may have a search_depth or max_depth parameter which can be specified to determine up to which depth a given element may be found. It's not recommended to have a big depth value as bigger depths mean that more items have to be traversed to find an element which can make such searches slower (so, more queries with a shalower depth is recommended over less queries with a bigger depth).

Working with locators in robocorp-windows

The term locator means a string which identifies how to reach an element in the application UI structure.

In the context of robocorp-windows it'll identify how to reach a window or some element inside the window (such as a combo box, text edit, etc).

With robocorp-windows, a basic inspector which can be used to identify the values which can be used in locators as well as testing locators can be used with the inspect() method for some element.

To start from the desktop, the API used would be:

from robocorp import windows windows.desktop().inspect()

Then, using the select window (activated with s:<optional window-related name> -- i.e.: s:note to filter for windows with note in the name) can be used to inspect elements inside a given window (follow the text prompts to know what's available).

After you have the locator for the window, it's recommended to start from the window directly:

Example with Notepad++:

from robocorp import windows windows.find_window('control:WindowControl class:Notepad++').inspect()

Usually the most useful approach is then asking for the highlight mouse (activated with m) and then hovering over the element of interest -- after a timeout with the mouse in the same position the related element should be highlighted and the information available to be used to reach it will be printed to the output.

Example:

Hovering over the record button of Notepad++ will print something as:

1-5. control:PaneControl class:ReBarWindow32 name:"" id:"" handle:0xB60560(11928928) Search info(depth:1 index:5 path:5) 2-1. control:ToolBarControl class:ToolbarWindow32 name:"" id:"" handle:0xA7110C(10948876) Search info(depth:2 index:1 path:5|1) 3-35. control:ButtonControl class:"" name:"Start Recording" id:"" handle:0x0(0) Search info(depth:3 index:35 path:5|1|35)

In this case some valid locators to reach it could be:

  • name:"Start Recording"
  • control:ButtonControl
  • class:ToolbarWindow32 > control:ButtonControl and name:"Start Recording"
  • path:5|1|35

Note that it's important to select a locator that will uniquely identify the element (so, for instance the control:ButtonControl may not be ideal because it may match other buttons in the UI).

Also, it's important to note that when a given element is printed, in the inspector you can interact with it to know whether it's actually valid, so, for instance, it's possible to test a locator with:

`h:control:ButtonControl`

to see which elements would be selected by it.

For the particular case of Notepad++, you may notice that doing something as h:name:"Start Recording" may fail to actually highlight any element.

In the Notepad++ case this happens because the buttons in the toolbar will only be accessible when the mouse is hovering over the toolbar.

In this case, the code to successfully access it would need to first hover over the toolbar:

window = windows.find_window("control:WindowControl class:Notepad++") toolbar = window.find("class:ToolbarWindow32") toolbar.mouse_hover() toolbar.find('name:"Start Recording"')

Also note that if you're targetting multiple versions of some application, it's possilbe to use more advanced expressions with or and and conditions (by default the and is not needed as a space will mean and implicitly).

For instance, the windows calculator has different ways to reach buttons depending on the Windows version, on some versions the name to reach it would be name:0 or name:Zero. In this case it'd be possible to write a locator such as class:Button and (name:0 or name:Zero).

Special keys

It's possible to send special keys (using the send_keys method) by wrapping the related code below with {} (Example: {Ctrl}, {Enter}).

Key codeKey description
LBUTTONLeft mouse button
RBUTTONRight mouse button
CANCELControl-break processing
MBUTTONMiddle mouse button (three-button mouse)
XBUTTON1X1 mouse button
XBUTTON2X2 mouse button
BACKBACKSPACE key
TABTAB key
CLEARCLEAR key
RETURNENTER key
ENTERENTER key
SHIFTSHIFT key
CTRLCTRL key
CONTROLCTRL key
ALTALT key
PAUSEPAUSE key
CAPITALCAPS LOCK key
KANAIME Kana mode
HANGUELIME Hanguel mode (maintained for compatibility; use VK_HANGUL)
HANGULIME Hangul mode
JUNJAIME Junja mode
FINALIME final mode
HANJAIME Hanja mode
KANJIIME Kanji mode
ESCESC key
ESCAPEESC key
CONVERTIME convert
NONCONVERTIME nonconvert
ACCEPTIME accept
MODECHANGEIME mode change request
SPACESPACEBAR
PRIORPAGE UP key
PAGEUPPAGE UP key
NEXTPAGE DOWN key
PAGEDOWNPAGE DOWN key
ENDEND key
HOMEHOME key
LEFTLEFT ARROW key
UPUP ARROW key
RIGHTRIGHT ARROW key
DOWNDOWN ARROW key
SELECTSELECT key
PRINTPRINT key
EXECUTEEXECUTE key
SNAPSHOTPRINT SCREEN key
PRINTSCREENPRINT SCREEN key
INSERTINS key
INSINS key
DELETEDEL key
DELDEL key
HELPHELP key
WINLeft Windows key (Natural keyboard)
LWINLeft Windows key (Natural keyboard)
RWINRight Windows key (Natural keyboard)
APPSApplications key (Natural keyboard)
SLEEPComputer Sleep key
NUMPAD0Numeric keypad 0 key
NUMPAD1Numeric keypad 1 key
NUMPAD2Numeric keypad 2 key
NUMPAD3Numeric keypad 3 key
NUMPAD4Numeric keypad 4 key
NUMPAD5Numeric keypad 5 key
NUMPAD6Numeric keypad 6 key
NUMPAD7Numeric keypad 7 key
NUMPAD8Numeric keypad 8 key
NUMPAD9Numeric keypad 9 key
MULTIPLYMultiply key
ADDAdd key
SEPARATORSeparator key
SUBTRACTSubtract key
DECIMALDecimal key
DIVIDEDivide key
F1F1 key
F2F2 key
F3F3 key
F4F4 key
F5F5 key
F6F6 key
F7F7 key
F8F8 key
F9F9 key
F10F10 key
F11F11 key
F12F12 key
F13F13 key
F14F14 key
F15F15 key
F16F16 key
F17F17 key
F18F18 key
F19F19 key
F20F20 key
F21F21 key
F22F22 key
F23F23 key
F24F24 key
NUMLOCKNUM LOCK key
SCROLLSCROLL LOCK key
LSHIFTLeft SHIFT key
RSHIFTRight SHIFT key
LCONTROLLeft CONTROL key
LCTRLLeft CONTROL key
RCONTROLRight CONTROL key
RCTRLRight CONTROL key
LALTLeft MENU key
RALTRight MENU key
BROWSER_BACKBrowser Back key
BROWSER_FORWARDBrowser Forward key
BROWSER_REFRESHBrowser Refresh key
BROWSER_STOPBrowser Stop key
BROWSER_SEARCHBrowser Search key
BROWSER_FAVORITESBrowser Favorites key
BROWSER_HOMEBrowser Start and Home key
VOLUME_MUTEVolume Mute key
VOLUME_DOWNVolume Down key
VOLUME_UPVolume Up key
MEDIA_NEXT_TRACKNext Track key
MEDIA_PREV_TRACKPrevious Track key
MEDIA_STOPStop Media key
MEDIA_PLAY_PAUSEPlay/Pause Media key
LAUNCH_MAILStart Mail key
LAUNCH_MEDIA_SELECTSelect Media key
LAUNCH_APP1Start Application 1 key
LAUNCH_APP2Start Application 2 key
OEM_1Used for miscellaneous characters; it can vary by keyboard.For the US standard keyboard, the ';:' key
OEM_PLUSFor any country/region, the '+' key
OEM_COMMAFor any country/region, the ',' key
OEM_MINUSFor any country/region, the '-' key
OEM_PERIODFor any country/region, the '.' key
OEM_2Used for miscellaneous characters; it can vary by keyboard.
OEM_3Used for miscellaneous characters; it can vary by keyboard.
OEM_4Used for miscellaneous characters; it can vary by keyboard.
OEM_5Used for miscellaneous characters; it can vary by keyboard.
OEM_6Used for miscellaneous characters; it can vary by keyboard.
OEM_7Used for miscellaneous characters; it can vary by keyboard.
OEM_8Used for miscellaneous characters; it can vary by keyboard.
OEM_102Either the angle bracket key or the backslash key on the RT 102-key keyboard
PROCESSKEYIME PROCESS key
PACKETUsed to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KeyUp
ATTNAttn key
CRSELCrSel key
EXSELExSel key
EREOFErase EOF key
PLAYPlay key
ZOOMZoom key
NONAMEReserved
PA1PA1 key
OEM_CLEARClear key