Speeding up execution

Aug 14, 2013 at 6:34 PM
Hi there,

I'm very new to powershell and am using it to try to automate some processes at work, i've got a few questions about how to speed this up some. After each block completes, there's a long pause.

Here is what I've got for code. Its taken directly from the UI Spy program for the most part.
Get-UIAWindow -Class 'ThunderRT6FormDC' -Name 'Administrator Tools' |
Get-UIAPane -Class 'SSTabCtlWndClass' | Get-UIAList  -AutomationId '29' -Class 'ThunderRT6ListBox' |
Invoke-UIAControlClick | Set-UIAControlText $User | Get-UIAListItem -Name $user | Invoke-UIAControlClick -DoubleClick;

Get-UIAWindow -Class 'ThunderRT6FormDC' -Name 'Administrator Tools' | `
Get-UIAPane -Class 'ToolbarWndClass' | `
Get-UIAToolBar -Class 'ToolbarWindow32' | `
Get-UIAButton -AutomationId 'Item 101' -Name 'Modify Current User' | Invoke-UIAControlClick;

Get-UIAWindow -Class 'ThunderRT6FormDC' -Name 'Administrator Tools' | `
Get-UIAPane -Class 'SSTabCtlWndClass' | `
Get-UIAPane -Class 'SSTabCtlWndClass' | `
Get-UIAEdit -AutomationId '45' -Class 'ThunderRT6TextBox' | Set-UIAControlText $userAbsent;

write-host "done";
Coordinator
Aug 14, 2013 at 9:53 PM
Edited Aug 15, 2013 at 6:29 AM
Hi jiffywhip,
first of all, the spy (as any code recorder) honestly writes all controls in the hierarchy exactly as they are placed in the Automation tree. Generated code is often a raw mass that I'd recommend to polish.
For example, in many cases you can cut out the -Class parameter. The parameter -AutomationId with value 29, 101 or 45 is a candidate to be cut out (it seems to be a value that application under test generated runtime).
We need (to the extent that controls remain recognizable) to shorten raw code in two ways:
1) it'd have less hops, i.e. get-uiawindow | get-control | get-control | get-control -> get-uiawindow | get-control | get-control or even get-uiawindow | get-control. Every hop is a query.
2) less properties are used for search (automatically generated AutomationIds (these 29 and 45), -Class that could sometimes vary from one operating system to another), i.e.
Get-control -class -name -automationid -> Get-control -name or Get-control -automationid
My version of this code would look like (it's just an imaginary example!):
Get-UIAWindow -Name *Admin*tools* | Get-UIAList  -Class 'ThunderRT6ListBox' |
Invoke-UIAControlClick | Set-UIAControlText $User | Get-UIAListItem -Name $user | Invoke-UIAControlClick -DoubleClick;

Get-UIAWindow -Name *Admin*tools* | `
Get-UIAToolBar -Class 'ToolbarWindow32' | `
Get-UIAButton -Name 'Modify Current User' | Invoke-UIAControlClick;

Get-UIAWindow -Name *Admin*tools* | `
Get-UIAEdit -Class 'ThunderRT6TextBox' | Set-UIAControlText $userAbsent;

write-host "done";
If the code waits for something AFTER each block of code, I think the problem is in getting the window. Supposing that the most of other windows are minimized or closed (the more normal/maximized windows, the slower UI Automation), I'd suggest experimenting with getting a window via process name, process id, process object or a combination:
Get-UIAWindow -pn calc
Get-UIAWindow -p (Get-Process calc)
Get-UIAWindow -pid (Get-Process calc).Id
Depending on which version you use (0.8.5, 0.8.6 betas), there could be more options, for example:
Get-UIAWindow -Win32 -Name *calc* # via EnumChildWindows
You can try several variants with the Measure-Command cmdlet:
Measure-Command -Expression { Get-UIAWindow -Name *calc*; }
Finally, if you need a lot of applications being run at the time you get a window, there may be a limitation (UIAutomation enumerates windows in a certain way. The more windows, the slower queries).
Another option for you is getting the desktop object and enumerating/filtering children:
Get-UIADesktop | Get-UIAControlChildren | ?{ $_.Current.Name -like "*calc*" }
this way at least demonstrates how many windows UI Automation enumerates.