Not only in the Get-UIA[ControlType] cmdlet family were introduced improvements. Another veteran, the Get-UIAWindow cmdlet has been modernized.
This is a start place for our experiments:
# there's an application with two forms open Start-Process calc -PassThru | Get-UIAWindow | Get-UIAMenuItem help | Invoke-UIAMenuItemExpand | Get-UIAMenuItem -n about* | Invoke-UIAMenuItemClick;
# using the Get-UIAChildWindow cmdlet Get-UIAWindow -pn calc | Get-UIAChildWindow; # using recursive search for a control of window type (in practice, the same as using the Get-UIAChildWindow cmdlet) Get-UIAWindow -pn calc | Get-UIAControl -ControlType Window;
These samples worked well for us until there were three or more windows open (the main form, the child form and a message box, for example. Another case is the main form and two child forms) or the main form is so complex that consists of two or more forms (dockable parts or a window inside an MMC application).
In such cases, the search for a certain window led to complicated code, especially when forms had the same captions.
Time changed, let’s review new ways of getting a certain window:
# the topmost window (there are no changes with the previous behavior) Get-UIAWindow -pn calc; # all windows of the process(es): Get-UIAWindow -pn calc -Recurse; # all windows with the phrase 'calc' in caption Get-UIAWindow -pn calc -Name *calc*; # all windows with the word 'about' in caption (in fact, it's only the child window) Get-UIAWindow -pn calc -Name *about*; # all windows with ClassName like 'frame' (the main window has Classname == 'CalcFrame') Get-UIAWindow -pn calc -Class *frame*; # all windows with ClassName == '#32770' (the child window has such a standard class name) Get-UIAWindow -pn calc -Class '#32770';
As can be easily seen, one call of the Get-UIAWindow cmdlet could substitute an old-days function of getting the right window.
The only problem in recursive search for windows is the time it could take: if forms are full of controls, the search will relatively slow.
Just to drop a couple of words about parameterless search. How many words could be used describing parameterless search?
Let’s dive into samples:
# the classic parameterless search for a control Start-Process calc -PassThru | Get-UIAWindow | Get-UIAButton -Name  | Invoke-UIAButtonClick; Get-UIAText 123;
# here we search for a control that has handle Start-Process calc -PassThru | Get-UIAWindow | Get-UIAButton -Name  | Invoke-UIAButtonClick; Get-UIAText 123 -Win32;
# using wildcards in parameterless search (-Win32 only) Start-Process calc -PassThru | Get-UIAWindow | Get-UIAButton -Name  | Invoke-UIAButtonClick; Get-UIAText 12* -Win32;
All three samples return the same: two labels (texts). However, you should understand that
- the first sample (i.e., Get-UIAText 123) works via MS UI Automation. This means that there is no use of wildcards. The query is (ControlType.Text AND (Name == ‘123’ OR AutomationId == ‘123’ OR ClassName == ‘123’ OR ValuePattern.Value == ‘123’)).
- the second and the third samples work via Win32 API (SendMessage) and check for the value given every AutomationElement with handle of given type
The only disadvantage of this syntax is a habit to supply all names with asterisks:
# MS UI Automation does not like asterisks: Get-UIAText 12*; # use the -Win32 parameter if applicable Get-UIAText 12* -Win32; # or the exact name, automation id, class name or value of a control Get-UIAText 123;
In simple situation this syntax helps make your code even simpler:
Start-Process calc -PassThru | Get-UIAWindow | Get-UIAMenuItem view | Invoke-UIAMenuItemExpand | Get-UIAMenuItem worksheets | Move-UIACursor -X 10 -Y 10 | Get-UIAMenuItem mortgage | Invoke-UIAMenuItemClick;
As you could notice, versions 0.8.3, 0.8.4 and 0.8.5 of the UIAutomation module took a few steps to be simpler and more friendly to the user. We carried out the following improvements to the module:
- added a Win32 click to the InvokePattern cmdlets (i.e., Invoke-UIAButtonClick, Invoke-UIAMenuItemClick, etc) in the case when pattern failed
- added the -Value parameter to Get-UIA[ControlType] cmdlets (i.e., Get-UIAEdit, etc)
- added the parameterless search like Get-UIAButton Next
- and we are working on an improvement to Set-UIAControlText and Set-UIAControlKeys cmdlets
Today’s post sheds light on the brand-new -Value parameter. Many controls support ValuePattern. The preceding link and this one give us the following definitions: “Represents a control that has an intrinsic value that does not span a range and can be represented as a string. This string may or may not be editable depending on the control and its settings.” “Allows clients to get or set a value on controls that do not support a range of values. For example, a date time picker.”
In practice, ValuePattern’s value is a string in a text field. Typically, it’s not wise to search for a text box by the value that is inside. It may be useful in certain situations (i.e., text boxes that are hard to recognize, for example, those that have auto-generated ids in AutomationId. And, in such situations, search for a control by a value in the field could help).
Start-Process calc -PassThru | Get-UIAWindow | Get-UIAButton -Name  | Invoke-UIAButtonClick; Get-UIAText -Value 123;
A better example is Computer Management -> Disk Management: while names of drives’ squares say the number of device and partition, values contain descriptive information:
Get-UIAWindow -Name *comp*manag* | Get-UIACustom -Value *unallocated*;
Where else the -Value parameter can be used? Accordingly to the suggested controls to patterns mapping, ValuePattern is useful when automating links.
For example, a link in an event’s help page in Event viewer:
Get-UIAWindow -n *event*event* | Get-UIAHyperlink -Value *event*log*online*;
What’s more, link’s href is available even it’s invisible:
Get-UIAWindow -n *control*pattern*mapping* | Get-UIAHyperlink -Value '*#control_mapping_clients*' | Read-UIAControlName;
Finally, the best area of applicability of the -Value parameter is grids and other complex controls.