Briefly, this beta release brings two features and several bug fixes:
The Keyboard property works, of course, with keys (for example, you could press Shift, send characters and release Shift). The Mouse property provides us with various clicks (this does not use handles, so that a window of your interest should be foreground).
Clicks that work via handles have been moved to the Control property:
$element.Click() -> $element.Control.Click()
$element.InvokeContextMenu() -> $element.Control.InvokeContextMenu()
I feel sorry to early adopters who could start using this, but a lot of properties directly on an automation element was a nightmare.
2) new logging. After moving to AOP, more and more possibilities are open. The new logger writes how cmdlets were called, with their parameters. String, int, bool (switch parameter) are represented as is. Automation elements are shown as hashtables. I hope that this logging will be much more useful in troubleshooting, for example, by analyzing what automation elements were passed to a cmdlet.
Now, new logging supports the most of cmdlets and properties and methods of the new object model. By default, it’s UIA.log in the Documents folder.
3) the Invoke-UiaWizard cmdlet became faster and much more reliable
4) the Invoke-UiaControlContextMenu cmdlet and the $element.Control.InvokeContextMenu() method have been working in not all situations, fixed
5) some more fixes I’m unable to remember what has been fixed in (getting controls in some situations that I found during writing of unit tests).
The first stable beta with the new elements’ object model is out! Now we have not only cmdlets, but also ‘short cuts’ via dotted notation:
$wnd = Start-Process calc -PassThru | Get-UiaWindow; $wnd.Descendants.Buttons['1'].Click(); $wnd.Descendants.MenuItems['view'].Expand() | Get-UiaMenuItem Standard | Invoke-UiaControlClick; $wnd.Descendants.MenuItems['view'].Expand() | Get-UiaMenuItem Worksheets | Move-UiaCursor -X 10 -Y 10 | Get-UiaMenuItem Mortgage | Invoke-UiaMenuItemClick; sleep -Seconds 2; $wnd.Descendants.Edits['purch*price'].Value = 123; $wnd.Descendants.MenuItems['view'].Expand() | Get-UiaMenuItem basic | Invoke-UiaMenuItemClick;
Sometimes one approach is better, sometimes another.
# may require running powershell as administrator $grid = Get-UiaWindow -n services | Get-UiaDataGrid; $grid.Descendants.DataItems['application*experience'].InvokeContextMenu() | Get-UiaMenuItem start | Invoke-UiaMenuItemClick;
Currently, the dotted object model does not support timeouts. It will be available in beta 2.
Many claim that it’s not so easy to decide which pattern cmdlet to use with a particular control. For long time we were tied to what Microsoft’s UI Automation outputs to us. However, there is a way to increase productivity: extension methods. Yes, they are not visible in PowerShell by default, nonetheless I’d like to offer an object model that grew from nothing else but extension methods.
To start, let’s page through the presentation, with binaries of 0.8.7 alpha 3 or higher in your hands. Enjoy!
I have found, absolutely occasionally, a set of slides about UIAutomation.
A great presentation, the author highlighted popular and useful features, pros and contras are described well.
Need to put here several notes:
page 9: Timeout = 60. The Timeout is in milliseconds (i.e., 60000) as Microsoft requires in Cmdlet Design Guidelines. They not always follow their rules (for example. the sleep cmdlet uses seconds), so that I created the -Seconds parameter for usability.
page 12: Lack of documentation – yes, it is. Here I need to admit the fact, the constant wish to describe the framework AFTER all features are done. Well, I need to continue documenting.
Last update and still Beta. I disagree on it. There are always workable binaries of a next version and all the binaries go the same testing and release process (and not only pre-versions are usually uploaded with the same quality as the ‘title’ version, but they as a rule contain fixes and improvements over ‘title’/’recommended’ binaries). To me, the version is a set of fixes and new features. If there are only fixes, such binaries simply could not be a new version, if there’s nothing new to offer.
Regarding the phrase ‘still Beta’, in my opinion, ‘release’ is a set of cmdlets and IDE, and improved spy, and several other things. I merely could not call cmdlets ‘release’ as they require knowledge of PowerShell to enter. An average software tester in not a PowerSheller, so that to be called ‘release’ the product should be simpler and more beautiful.
I hope that my position here is clear, and cmdlets are practically ‘release’. However, the full set of software (cmdlets, UIARunner, UIAutomationSpy, missing IDE, embedded test management ,etc ,etc) is not release yet.
I’d like to discuss the page 13 (hey, author), especially the third and the fourth items – I believe that RD (Remote Desktop?) is not a problem, just a place to implement some settings. I use Remote desktop via RemoteApp widely and have no issues here.
The second item is not my fault as I suspect (the framework follows MS UI Automation here), the third item I don’t understand. The first item may need explanation: if the author (as seen on the pictures) tested a wizard, especially a setup wizard, there could be a problem with wizard pages. Wizard switches pages and the handle of window changes. The scripter should get window every step, and this is implemented in wizard cmdlets (in later betas of 0.8.6).
To conclude, Juraj created an excellent presentation, for community and for me to understand better what the frameworks consumers think.
Have I not mentioned yet that all sample scripts are constantly available online? Scripts that are honored to be public are always put in the folder that is checked in to the source control. Here is the root of the samples folder: https://github.com/apetrovskiy/STUPS/tree/master/samples
For instance, UIAutomation samples are here: https://github.com/apetrovskiy/STUPS/tree/master/samples/UIAutomation, TMX samples are here https://github.com/apetrovskiy/STUPS/tree/master/samples/TMX and so on.
Unfortunately, some scripts may become incompatible with the contemporary versions of binaries. Sometimes I refresh them, alternatively, you could initiate a pull request with a renewed version of a script.
As I heard, there were a million test cases in PowerShell v. 1.0. In PowerShell ISE v. 3.0 I faced the following bug (a repeatable bug), on a Windows 8 x64 box:
1. In ISE have been opened several script modules.
2. ISE was closed
3. Two modules have been renamed (like XXXTestCasesIteration1.psm1 -> XXXTestCasesIteration01.psm1) and their folders were also renamed (i.e., XXXTestCasesIteration1\XXXTestCasesIteration1.psm1 -> XXXTestCasesIteration01\XXXTestCasesIteration01.psm1)
4. ISE was opened again and one of renamed files was called via Recent with a right (and a bit verbose) message box.
5. After that, I opened the Open menu item, a second thereafter ISE crashed.
After crash, it points (on selecting the Open menu item) to the %SystemRoot%\system32\WindowsPowerShell\v1.0 folder (i.e., where the executable is situated).
How to repeat? I opened a file in a next to folder to renamed (to point the last folder to a similar place), performed steps 1-5 with the second module (i.e., XXXTestCasesIteration2\XXXTestCasesIteration2.psm1 -> XXXTestCasesIteration02\XXXTestCasesIteration02.psm1) and the answer from ISE was the same, crash. Arr!
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;
Even though we added support of Java SWT application months ago, in 0.8.0 Preview 5 or even earlier, we’ve never declared this fact. There’s a script within UIAutomation 0.8.5 packages that installs Java Access Bridge libraries by Oracle accordingly to this page: Installing Java Access Bridge.
All that you need to do is
- download the binaries (see inside the script)
- change a couple of variables to meet paths to Java on your host
- save and run the script As Administrator
Here are screenshots which abilities Oracle/Sun adds to our tools (Eclipse Indigo):
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.