Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple sample for access the MS UIAutomation in PowerShell. #devsample #win
#REQUIRES -Version 3.0
# This is a simple sample for access the MS UIAutomation in PowerShell.
# In this sample:
# 1. Load the MS UIA via System.Reflection.Assembly
# 2. Launch the AUT ( calc.exe )
# 3. Find the AutomationElement via the AUT Process Id
# 4. Find buttons via 'ClassName' and 'Name' property
# 5. Click the '1', '+', '1', '=' buttons.
# At last, we will get '2' in the result of calc App.
# Load MS UIAutomation assemblies
Write-Host "Loading MS UIA assemblies"
[void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationClient")
[void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationTypes")
[void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationProvider")
[void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationClientsideProviders")
# Register client side provider
Write-Host "Register client-side provider"
$client = [System.Reflection.Assembly]::LoadWithPartialName("UIAutomationClientsideProviders")
[Windows.Automation.ClientSettings]::RegisterClientSideProviderAssembly($client.GetName())
# Launch the AUT ( calc.exe ) & sleep 10 seconds for wait the process start
Write-Host "Launching the AUT"
$autProc = Start-Process calc -PassThru
Start-Sleep -s 10
# Find the calc Element via the process Id
Write-Host "Searching the AUT Root element"
$rootElement = [Windows.Automation.AutomationElement]::RootElement
$condAUTProc = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ProcessIdProperty, $autProc.Id)
$autElement = $rootElement.FindFirst([Windows.Automation.TreeScope]::Children, $condAUTProc)
# Find the buttons '1', '+', '='
Write-Host "Searching the button elements"
$condBtn = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ClassNameProperty, "Button")
$condName = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "1")
$condTarget = New-Object Windows.Automation.AndCondition($condBtn, $condName)
$btn1Element = $autElement.FindFirst([Windows.Automation.TreeScope]::Descendants, $condTarget)
$condName = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "+")
$condTarget = New-Object Windows.Automation.AndCondition($condBtn, $condName)
$btnPlusElement = $autElement.FindFirst([Windows.Automation.TreeScope]::Descendants, $condTarget)
$condName = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "=")
$condTarget = New-Object Windows.Automation.AndCondition($condBtn, $condName)
$btnEqualElement = $autElement.FindFirst([Windows.Automation.TreeScope]::Descendants, $condTarget)
# Click the buttons
Write-Host "Clicking the buttons"
$btn1Element.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern).Invoke()
Start-Sleep -s 1
$btnPlusElement.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern).Invoke()
Start-Sleep -s 1
$btn1Element.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern).Invoke()
Start-Sleep -s 1
$btnEqualElement.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern).Invoke()
Start-Sleep -s 1
Write-Host "Finished. Please check the results on the AUT."
@johndonnelly

This comment has been minimized.

Copy link

commented Feb 13, 2016

Nice script but I get "You cannot call a method on a null-valued expression." on line 56 and 60. It seems the + and the = button element objects aren't created?

@DBremen

This comment has been minimized.

Copy link

commented Mar 3, 2016

Hi @johndonnelly,
I just came across the same gist. Using UIA Verify http://uiautomationverify.codeplex.com/releases/view/11366 I was able to find out that the button names are "Add" and "Equals" respectively (Windows 7). Changing lines 44.48 to the correct names made it work:

`$condName = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Add")

$condName = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Equals")`

@smartaquarius10

This comment has been minimized.

Copy link

commented Jun 15, 2017

Script is working fine in debug mode. But getting this error when I try to call ps1 from bat script:

Exception calling "RegisterClientSideProviderAssembly" with "1" argument(s):
"Object reference not set to an instance of an object."
At C:\Users\Public\Desktop\Untitled.ps1:6 char:2
+  [Windows.Automation.ClientSettings]::RegisterClientSideProviderAssem ...
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NullReferenceException

Can anyone help..

@george-chakhidze

This comment has been minimized.

Copy link

commented Sep 28, 2017

@smartaquarius10 That's very unusual bug, - looks like when calling RegisterClientSideProviderAssembly from powershell.exe, first call fails with exception and all subsequent calls will be successful! Here is a workaround:

try
{
    # WORKAROUND: There is a weird bug: first call fails ...
    [Windows.Automation.ClientSettings]::RegisterClientSideProviderAssembly([UIAutomationClientsideProviders.UIAutomationClientSideProviders].Assembly.GetName())
}
catch {}
# ... second call succeeds:
[Windows.Automation.ClientSettings]::RegisterClientSideProviderAssembly([UIAutomationClientsideProviders.UIAutomationClientSideProviders].Assembly.GetName())

after this script works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.