Last active
November 29, 2022 18:44
-
-
Save xiongjia/6749035 to your computer and use it in GitHub Desktop.
A simple sample for access the MS UIAutomation in PowerShell. #devsample #win
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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." |
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..
@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
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")`