You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非交互模式执行PowerShell脚本时出现Unsupported Pattern异常

问题:PowerShell脚本逐行执行正常,批量运行时UIAutomation报错"Unsupported Pattern"

我想用PowerShell静默卸载程序,流程是通过Winget启动卸载,再用UIAutomation点击卸载确认按钮。逐行交互执行脚本时多次测试都正常,但从文件运行或粘贴整个脚本块到PowerShell时,出现以下错误:

Exception calling "GetCurrentPattern" with "1" argument(s): "Unsupported Pattern."

试过在每个操作后加Start-Sleep排查,没用;也换过不同PowerShell版本、系统上下文运行脚本,问题依旧。完整脚本如下:

#import required assemblies
Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes

#find and run winget (script runs in system context and cant find winget, but directly referencing .exe works)
$winget = "$env:programfiles\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe"
&$winget uninstall dropbox --Disable-Interactivity

#find drobbox uninstaller process
$DBUninstallProc = (Get-Process | Where-Object {$_.ProcessName -eq 'Au_'})
#wait for GUI to load
$null = $DBUninstallProc.WaitForInputIdle(5000)

#get root element
$root = [Windows.Automation.AutomationElement]::RootElement

#Create a PropertyCondition used to grab the Uninstaller Window
$GetDBWindowCondition = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ProcessIdProperty, $DBUninstallProc.Id)

#Get the Uninstaller window
$DBUninstallerUI = $root.FindFirst([Windows.Automation.TreeScope]::Children, $GetDBWindowCondition)

#Find the uninstall button
$UninstallButtonCondition = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Uninstall")
$button = $DBUninstallerUI.FindFirst([Windows.Automation.TreeScope]::Descendants, $UninstallButtonCondition)

#Click the uninstall button
$button.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern) #.Invoke();
解决方案

问题根源是批量运行时,UI元素还未完全初始化就被脚本尝试访问,WaitForInputIdle无法保证UI控件的Pattern已经就绪。可以从以下几点优化:

  • 循环等待窗口和控件就绪
    不要只等待进程空闲,要循环检查窗口和按钮元素是否存在,以及控件是否支持InvokePattern:

    # 等待卸载器窗口出现
    $DBUninstallerUI = $null
    while (-not $DBUninstallerUI) {
        Start-Sleep -Milliseconds 500
        $DBUninstallerUI = $root.FindFirst([Windows.Automation.TreeScope]::Children, $GetDBWindowCondition)
    }
    
    # 等待Uninstall按钮出现并确认支持InvokePattern
    $button = $null
    $invokePattern = $null
    while (-not $invokePattern) {
        Start-Sleep -Milliseconds 500
        $button = $DBUninstallerUI.FindFirst([Windows.Automation.TreeScope]::Descendants, $UninstallButtonCondition)
        if ($button) {
            try {
                $invokePattern = $button.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern)
            }
            catch {
                # 控件还未就绪,继续等待
                $button = $null
            }
        }
    }
    
    # 执行点击
    $invokePattern.Invoke()
    
  • 改进进程查找逻辑
    原脚本中Get-Process | Where-Object {$_.ProcessName -eq 'Au_'}可能匹配多个进程,或者进程还未启动就查找,改成循环查找直到进程存在:

    $DBUninstallProc = $null
    while (-not $DBUninstallProc) {
        Start-Sleep -Milliseconds 500
        $DBUninstallProc = Get-Process -Name 'Au_' -ErrorAction SilentlyContinue
    }
    
  • 调整Winget执行方式
    使用Start-Process并等待Winget启动卸载器后再继续,避免脚本超前执行:

    Start-Process -FilePath $winget -ArgumentList "uninstall dropbox --Disable-Interactivity" -Wait -NoNewWindow
    

整合后的完整脚本:

# 导入所需程序集
Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes

# 定位Winget路径(避免通配符匹配多个版本)
$wingetPath = Get-ChildItem -Path "$env:programfiles\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe" | Select-Object -Last 1 -ExpandProperty FullName
if (-not $wingetPath) {
    Write-Error "未找到Winget可执行文件"
    exit 1
}

# 启动Winget卸载Dropbox并等待操作完成
Start-Process -FilePath $wingetPath -ArgumentList "uninstall dropbox --Disable-Interactivity" -Wait -NoNewWindow

# 循环查找Dropbox卸载器进程
$DBUninstallProc = $null
while (-not $DBUninstallProc) {
    Start-Sleep -Milliseconds 500
    $DBUninstallProc = Get-Process -Name 'Au_' -ErrorAction SilentlyContinue
}

# 等待进程进入空闲状态
$null = $DBUninstallProc.WaitForInputIdle(5000)

# 获取UI自动化根元素
$root = [Windows.Automation.AutomationElement]::RootElement

# 创建卸载窗口查找条件(按进程ID匹配)
$windowCondition = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ProcessIdProperty, $DBUninstallProc.Id)

# 循环等待卸载窗口出现
$uninstallWindow = $null
while (-not $uninstallWindow) {
    Start-Sleep -Milliseconds 500
    $uninstallWindow = $root.FindFirst([Windows.Automation.TreeScope]::Children, $windowCondition)
}

# 创建卸载按钮查找条件(按名称匹配)
$buttonCondition = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Uninstall")

# 循环等待按钮就绪并获取InvokePattern
$invokePattern = $null
while (-not $invokePattern) {
    Start-Sleep -Milliseconds 500
    $button = $uninstallWindow.FindFirst([Windows.Automation.TreeScope]::Descendants, $buttonCondition)
    if ($button) {
        try {
            $invokePattern = $button.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern)
        }
        catch {
            # 控件未完全初始化,重置按钮对象继续等待
            $button = $null
        }
    }
}

# 执行按钮点击操作
$invokePattern.Invoke()

内容的提问来源于stack exchange,提问作者jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:40:01