Skip to content

Instantly share code, notes, and snippets.

@xiongjia
Last active November 29, 2022 18:44
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save xiongjia/6749035 to your computer and use it in GitHub Desktop.
Save xiongjia/6749035 to your computer and use it in GitHub Desktop.
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."
@DBremen
Copy link

DBremen 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")`

@tanulbh
Copy link

tanulbh 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
Copy link

george-chakhidze 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