powershell 通过调用 .net 的 uiautomationclient 实现 ui 自动化,核心是 automationelement 类;可获取顶层窗口、按进程名定位应用、遍历子控件筛选按钮/文本框等,并需注意权限、应用类型及性能优化。
powershell 本身不直接提供图形界面(gui)控件操作能力,但它可以通过调用 .net framework / .net core 的 windows forms 或 wpf 类库,结合 ui 自动化框架(如 uiautomation)来查询和交互 windows 界面中的 ui 元素。真正实现“自动化查询 ui 元素”的核心是 windows ui automation api,powershell 通过 [system.windows.automation.automationelement] 类来访问它。
使用 UIAutomation 查询桌面顶层窗口
这是最基础的起点:获取当前屏幕上的主窗口列表,比如记事本、浏览器、资源管理器等。
- 加载 UIAutomation 命名空间:
Add-Type -AssemblyName UIAutomationClient - 获取桌面根元素:
$desktop = [System.Windows.Automation.AutomationElement]::RootElement - 查找所有顶级窗口(Visible + Enabled):
$topWindows = $desktop.FindAll([System.Windows.Automation.TreeScope]::Children, [System.Windows.Automation.Condition]::TrueCondition) - 筛选出标题非空、可见的窗口:
$topWindows | Where-Object { $_.GetCurrentPropertyValue([System.Windows.Automation.AutomationElementIdentifiers]::NameProperty) -and $_.GetCurrentPropertyValue([System.Windows.Automation.AutomationElementIdentifiers]::IsOffscreenProperty) -eq $false }
按窗口标题或进程名精准定位目标应用
实际脚本中通常需要找到特定程序(如“计算器”或“notepad.exe”)的主窗口,再进一步查询其内部控件。
- 先通过进程名获取 PID,再用
AutomationElement.FromIAccessible或FindFirst配合ProcessIdCondition定位: $condition = New-Object System.Windows.Automation.PropertyCondition ([System.Windows.Automation.AutomationElementIdentifiers]::ProcessIdProperty), (Get-Process notepad).Id$notepadWindow = $desktop.FindFirst([System.Windows.Automation.TreeScope]::Children, $condition)- 确认是否找到:
if ($notepadWindow) { Write-Host "找到记事本窗口:" $notepadWindow.GetCurrentPropertyValue([System.Windows.Automation.AutomationElementIdentifiers]::NameProperty) }
遍历子控件并按控件类型/名称筛选按钮、文本框等
进入目标窗口后,常用 TreeScope.Descendants 查找所有嵌套元素,并用 PropertyCondition 过滤关键控件。
- 查找所有按钮:
$buttons = $notepadWindow.FindAll([System.Windows.Automation.TreeScope]::Descendants, (New-Object System.Windows.Automation.PropertyCondition ([System.Windows.Automation.AutomationElementIdentifiers]::ControlTypeProperty), [System.Windows.Automation.ControlType]::Button)) - 查找名称含“保存”的按钮:
$saveBtn = $notepadWindow.FindFirst([System.Windows.Automation.TreeScope]::Descendants, (New-Object System.Windows.Automation.AndCondition ((New-Object System.Windows.Automation.PropertyCondition ([System.Windows.Automation.AutomationElementIdentifiers]::ControlTypeProperty), [System.Windows.Automation.ControlType]::Button)), (New-Object System.Windows.Automation.PropertyCondition ([System.Windows.Automation.AutomationElementIdentifiers]::NameProperty), "保存"))) - 获取编辑框内容:
$edit = $notepadWindow.FindFirst([System.Windows.Automation.TreeScope]::Descendants, (New-Object System.Windows.Automation.PropertyCondition ([System.Windows.Automation.AutomationElementIdentifiers]::ControlTypeProperty), [System.Windows.Automation.ControlType]::Edit)); $edit.GetCurrentPropertyValue([System.Windows.Automation.AutomationElementIdentifiers]::ValueProperty)
注意事项与常见问题
UI Automation 在不同应用、DPI 设置、UAC 权限下行为可能不一致,需注意以下几点:
- 脚本需以与目标应用相同的完整性级别运行(例如目标程序以管理员运行,PowerShell 也需管理员权限)
- UWP 应用(如新版记事本、设置)支持有限,部分控件可能无法被识别或属性为空
- 某些 Electron 或 Qt 应用未正确实现 UIA 接口,导致 FindAll 返回空或结构异常
- 避免过度递归搜索;建议用
TreeScope.Children逐层缩小范围,提升性能和稳定性 - 查询前可加短暂停顿(
Start-Sleep -Milliseconds 100),确保 UI 渲染完成











