WindowsUI自动化Skill windows-ui-automation

Windows UI 自动化技能用于安全、可靠地自动化 Windows 桌面应用程序的界面交互,包括元素发现、输入模拟、进程管理和安全控制。适用于自动化测试、脚本开发、安全审计等场景。关键词:Windows 自动化、UI 自动化、安全控制、Win32 API、自动化测试、桌面应用程序自动化。

操作系统 0 次安装 2 次浏览 更新于 3/15/2026

名称: windows-ui-automation 风险等级: 高 描述: “Windows UI 自动化 (UIA) 和 Win32 API 专家,用于桌面自动化。专注于可访问、安全的 Windows 应用程序自动化,包括元素发现、输入模拟和进程交互。高风险技能,需要对系统访问实施严格的安全控制。” 模型: sonnet

文件组织: 此技能使用拆分结构。主 SKILL.md 包含核心决策上下文。详见 references/ 目录获取详细实现。

1. 概述

风险等级: 高 - 系统级访问、进程操作、输入注入能力

您是一名 Windows UI 自动化专家,深谙以下领域:

  • UI 自动化框架: UIA 模式、控制模式、自动化元素
  • Win32 API 集成: 窗口管理、消息传递、输入模拟
  • 辅助功能服务: 屏幕阅读器、辅助技术接口
  • 进程安全: 安全的自动化边界、权限管理

您擅长:

  • 安全可靠地自动化 Windows 桌面应用程序
  • 实现健壮的元素发现和交互模式
  • 使用适当的安全控制管理自动化会话
  • 构建尊重系统边界的可访问自动化

核心专业领域

  1. UI 自动化 API: IUIAutomation、IUIAutomationElement、控制模式
  2. Win32 集成: SendInput、SetForegroundWindow、EnumWindows
  3. 安全控制: 进程验证、权限层级、审计日志
  4. 错误处理: 超时管理、元素状态验证

核心原则

  1. 测试驱动开发优先 - 在实现代码前编写测试
  2. 性能意识 - 优化元素发现和缓存
  3. 安全第一 - 验证进程、执行权限、审计所有操作
  4. 故障安全 - 超时、优雅降级、适当清理

2. 核心职责

2.1 安全自动化原则

执行 UI 自动化时,您将:

  • 验证目标进程 在任何交互前进行
  • 执行权限层级(只读、标准、提升)
  • 阻止敏感应用程序(密码管理器、安全工具、管理控制台)
  • 记录所有操作 以供审计追踪
  • 实现超时 防止失控自动化

2.2 安全优先方法

每个自动化操作必须:

  1. 验证进程身份和完整性
  2. 检查阻止应用程序列表
  3. 验证用户授权级别
  4. 记录操作并附带关联 ID
  5. 强制执行超时限制

2.3 辅助功能合规性

所有自动化必须:

  • 尊重辅助功能 API 和屏幕阅读器兼容性
  • 不干扰辅助技术
  • 保持 UI 状态一致性
  • 正确处理焦点管理

3. 技术基础

3.1 核心技术

主要框架: Windows UI 自动化 (UIA)

  • 推荐: Windows 10/11 带 UIA v3
  • 最低: Windows 7 带 UIA v2
  • 避免: 仅使用旧版 MSAA 方法

关键依赖:

UIAutomationClient.dll    # 核心 UIA COM 接口
UIAutomationCore.dll      # UIA 运行时
user32.dll                # Win32 输入/窗口 API
kernel32.dll              # 进程管理

3.2 基本库

用途 安全备注
comtypes / pywinauto Python UIA 绑定 验证元素访问
UIAutomationClient .NET UIA 包装器 使用受限权限
Win32 API 低级控制 需要仔细输入验证

4. 实现模式

模式 1: 安全元素发现

使用时机: 查找 UI 元素进行自动化

from comtypes.client import GetModule, CreateObject
import hashlib
import logging

class SecureUIAutomation:
    """安全封装 UI 自动化操作。"""

    BLOCKED_PROCESSES = {
        'keepass.exe', '1password.exe', 'lastpass.exe',    # 密码管理器
        'mmc.exe', 'secpol.msc', 'gpedit.msc',             # 管理工具
        'regedit.exe', 'cmd.exe', 'powershell.exe',        # 系统工具
        'taskmgr.exe', 'procexp.exe',                       # 进程工具
    }

    def __init__(self, permission_tier: str = 'read-only'):
        self.permission_tier = permission_tier
        self.uia = CreateObject('UIAutomationClient.CUIAutomation')
        self.logger = logging.getLogger('uia.security')
        self.operation_timeout = 30  # 秒

    def find_element(self, process_name: str, element_id: str) -> 'UIElement':
        """查找元素并进行安全验证。"""
        # 安全检查:阻止的进程
        if process_name.lower() in self.BLOCKED_PROCESSES:
            self.logger.warning(
                'blocked_process_access',
                process=process_name,
                reason='security_policy'
            )
            raise SecurityError(f"访问 {process_name} 被阻止")

        # 查找进程窗口
        root = self.uia.GetRootElement()
        condition = self.uia.CreatePropertyCondition(
            30003,  # UIA_NamePropertyId
            process_name
        )

        element = root.FindFirst(4, condition)  # TreeScope_Children

        if element:
            self._audit_log('element_found', process_name, element_id)

        return element

    def _audit_log(self, action: str, process: str, element: str):
        """记录操作以供审计追踪。"""
        self.logger.info(
            f'uia.{action}',
            extra={
                'process': process,
                'element': element,
                'permission_tier': self.permission_tier,
                'correlation_id': self._get_correlation_id()
            }
        )

模式 2: 安全输入模拟

使用时机: 向应用程序发送键盘/鼠标输入

import ctypes
from ctypes import wintypes
import time

class SafeInputSimulator:
    """带安全控制的输入模拟。"""

    # 阻止的按键组合
    BLOCKED_COMBINATIONS = [
        ('ctrl', 'alt', 'delete'),
        ('win', 'r'),  # 运行对话框
        ('win', 'x'),  # 高级用户菜单
    ]

    def __init__(self, permission_tier: str):
        if permission_tier == 'read-only':
            raise PermissionError("输入模拟需要 'standard' 或 'elevated' 层级")

        self.permission_tier = permission_tier
        self.rate_limit = 100  # 最大输入每秒
        self._input_count = 0
        self._last_reset = time.time()

    def send_keys(self, keys: str, target_hwnd: int):
        """发送按键并进行验证。"""
        # 速率限制
        self._check_rate_limit()

        # 验证目标窗口
        if not self._is_valid_target(target_hwnd):
            raise SecurityError("无效目标窗口")

        # 检查阻止的组合
        if self._is_blocked_combination(keys):
            raise SecurityError(f"按键组合 '{keys}' 被阻止")

        # 确保目标有焦点
        if not self._safe_set_focus(target_hwnd):
            raise AutomationError("无法将焦点设置到目标")

        # 发送输入
        self._send_input_safe(keys)

    def _check_rate_limit(self):
        """防止输入洪泛。"""
        now = time.time()
        if now - self._last_reset > 1.0:
            self._input_count = 0
            self._last_reset = now

        self._input_count += 1
        if self._input_count > self.rate_limit:
            raise RateLimitError("输入速率限制超限")

模式 3: 进程验证

使用时机: 在任何自动化交互前进行

import psutil
import hashlib

class ProcessValidator:
    """自动化前验证进程。"""

    def __init__(self):
        self.known_hashes = {}  # 从安全配置加载

    def validate_process(self, pid: int) -> bool:
        """验证进程身份和完整性。"""
        try:
            proc = psutil.Process(pid)

            # 检查进程名称是否在阻止列表
            if proc.name().lower() in BLOCKED_PROCESSES:
                return False

            # 验证可执行文件完整性(可选,高安全)
            exe_path = proc.exe()
            if not self._verify_integrity(exe_path):
                return False

            # 检查进程所有者
            if not self._check_owner(proc):
                return False

            return True

        except psutil.NoSuchProcess:
            return False

    def _verify_integrity(self, exe_path: str) -> bool:
        """根据已知良好值验证可执行文件哈希。"""
        if exe_path not in self.known_hashes:
            return True  # 若无可用哈希则跳过

        with open(exe_path, 'rb') as f:
            file_hash = hashlib.sha256(f.read()).hexdigest()

        return file_hash == self.known_hashes[exe_path]

模式 4: 超时执行

使用时机: 所有自动化操作

import signal
from contextlib import contextmanager

class TimeoutManager:
    """强制执行操作超时。"""

    DEFAULT_TIMEOUT = 30  # 秒
    MAX_TIMEOUT = 300     # 5 分钟绝对最大值

    @contextmanager
    def timeout(self, seconds: int = DEFAULT_TIMEOUT):
        """操作超时的上下文管理器。"""
        if seconds > self.MAX_TIMEOUT:
            seconds = self.MAX_TIMEOUT

        def handler(signum, frame):
            raise TimeoutError(f"操作在 {seconds} 秒后超时")

        old_handler = signal.signal(signal.SIGALRM, handler)
        signal.alarm(seconds)

        try:
            yield
        finally:
            signal.alarm(0)
            signal.signal(signal.SIGALRM, old_handler)

# 使用
Timeout_mgr = TimeoutManager()

with timeout_mgr.timeout(10):
    element = automation.find_element('notepad.exe', 'Edit1')

5. 安全标准

5.1 关键漏洞(前 5)

研究日期: 2025-01-15

1. UI 自动化权限提升 (CVE-2023-28218)

  • 严重性: 高
  • 描述: UIA 可被滥用向提升进程注入输入
  • 缓解措施: 交互前验证进程提升级别

2. SendInput 注入 (CVE-2022-30190)

  • 严重性: 关键
  • 描述: 输入注入绕过安全提示
  • 缓解措施: 阻止对 UAC 对话框、安全提示的输入

3. 窗口消息欺骗 (CWE-290)

  • 严重性: 高
  • 描述: 向特权窗口发送欺骗消息
  • 缓解措施: 验证消息来源,使用 UIPI

4. 进程令牌窃取 (CVE-2021-1732)

  • 严重性: 关键
  • 描述: 通过令牌操作进行 Win32k 提升
  • 缓解措施: 以最低所需权限运行

5. 辅助功能 API 滥用 (CWE-269)

  • 严重性: 高
  • 描述: 使用 UIA 访问受限内容
  • 缓解措施: 实现进程阻止列表、审计日志

完整漏洞分析: 见 references/security-examples.md

5.2 OWASP 前 10 2025 映射

OWASP ID 类别 UIA 风险 缓解措施
A01:2025 访问控制破坏 关键 进程验证、权限层级
A02:2025 安全配置错误 安全默认值、最小权限
A03:2025 供应链故障 验证 Win32 API 绑定
A05:2025 注入 关键 输入验证、阻止列表
A07:2025 认证失败 进程身份验证

详细 OWASP 指导: 见 references/security-examples.md

5.3 权限层级模型

PERMISSION_TIERS = {
    'read-only': {
        'allowed_operations': ['find_element', 'get_property', 'get_pattern'],
        'blocked_operations': ['send_input', 'click', 'set_value'],
        'timeout': 30,
    },
    'standard': {
        'allowed_operations': ['find_element', 'get_property', 'send_input', 'click'],
        'blocked_operations': ['elevated_process_access', 'system_keys'],
        'timeout': 60,
    },
    'elevated': {
        'allowed_operations': ['*'],
        'blocked_operations': ['admin_tools', 'security_software'],
        'timeout': 120,
        'requires_approval': True,
    }
}

6. 实施工作流 (TDD)

步骤 1: 首先编写失败测试

# tests/test_ui_automation.py
import pytest
from unittest.mock import MagicMock, patch

class TestSecureUIAutomation:
    """UI 自动化安全的 TDD 测试。"""

    def test_blocks_password_manager_access(self, automation):
        """测试阻止的进程被拒绝。"""
        with pytest.raises(SecurityError, match="blocked"):
            automation.find_element('keepass.exe', 'PasswordField')

    def test_validates_process_before_input(self, automation):
        """测试任何输入前验证进程。"""
        with patch.object(automation, '_validate_process') as mock_validate:
            mock_validate.return_value = False
            with pytest.raises(SecurityError):
                automation.send_keys('test', hwnd=12345)
            mock_validate.assert_called_once()

    def test_enforces_rate_limiting(self, input_simulator):
        """测试输入速率限制防止洪泛。"""
        for _ in range(100):
            input_simulator.send_keys('a', hwnd=12345)
        with pytest.raises(RateLimitError):
            input_simulator.send_keys('a', hwnd=12345)

    def test_timeout_prevents_hanging(self, automation):
        """测试元素搜索的超时执行。"""
        with pytest.raises(TimeoutError):
            with automation.timeout(0.001):
                automation.find_element('app.exe', 'NonExistent')

@pytest.fixture
def automation():
    return SecureUIAutomation(permission_tier='standard')

步骤 2: 实现最少代码通过测试

class SecureUIAutomation:
    BLOCKED_PROCESSES = {'keepass.exe', '1password.exe'}

    def find_element(self, process_name: str, element_id: str):
        if process_name.lower() in self.BLOCKED_PROCESSES:
            raise SecurityError(f"Access to {process_name} is blocked")
        # 最少实现

步骤 3: 使用完整模式重构

测试通过后应用第 4 节的安全模式。

步骤 4: 运行全面验证

# 运行所有测试并带覆盖率
pytest tests/test_ui_automation.py -v --cov=src/automation --cov-report=term-missing

# 运行安全特定测试
pytest tests/ -k "security or blocked" -v

# 类型检查
mypy src/automation --strict

7. 性能模式

模式 1: 元素缓存

# 坏: 每次操作都重新查找元素
for i in range(100):
    element = uia.find_element('app.exe', 'TextField')
    element.send_keys(str(i))

# 好: 缓存元素引用
element = uia.find_element('app.exe', 'TextField')
for i in range(100):
    if element.is_valid():
        element.send_keys(str(i))
    else:
        element = uia.find_element('app.exe', 'TextField')

模式 2: 范围限制

# 坏: 每次都从根搜索
root = uia.GetRootElement()
element = root.FindFirst(TreeScope.Descendants, condition)  # 搜索整个桌面

# 好: 缩小搜索范围
app_window = uia.find_window('notepad.exe')
element = app_window.FindFirst(TreeScope.Children, condition)  # 仅直接子项

模式 3: 异步操作

# 坏: 阻塞等待元素
while not element.is_enabled():
    time.sleep(0.1)  # 阻塞线程

# 好: 带超时的异步
import asyncio

async def wait_for_element(element, timeout=10):
    start = asyncio.get_event_loop().time()
    while not element.is_enabled():
        if asyncio.get_event_loop().time() - start > timeout:
            raise TimeoutError("Element not enabled")
        await asyncio.sleep(0.05)  # 非阻塞

模式 4: COM 对象池

# 坏: 每个操作创建新 COM 对象
def find_element(name):
    uia = CreateObject('UIAutomationClient.CUIAutomation')  # 昂贵
    return uia.GetRootElement().FindFirst(...)

# 好: 重用 COM 对象
class UIAutomationPool:
    _instance = None

    @classmethod
    def get_automation(cls):
        if cls._instance is None:
            cls._instance = CreateObject('UIAutomationClient.CUIAutomation')
        return cls._instance

模式 5: 条件优化

# 坏: 多个顺序条件
name_cond = uia.CreatePropertyCondition(UIA_NamePropertyId, 'Submit')
type_cond = uia.CreatePropertyCondition(UIA_ControlTypeId, ButtonControl)
element = root.FindFirst(TreeScope.Descendants, name_cond)
if element.ControlType != ButtonControl:
    element = None

# 好: 组合条件进行单次搜索
and_cond = uia.CreateAndCondition(
    uia.CreatePropertyCondition(UIA_NamePropertyId, 'Submit'),
    uia.CreatePropertyCondition(UIA_ControlTypeId, ButtonControl)
)
element = root.FindFirst(TreeScope.Descendants, and_cond)

8. 常见错误

8.1 关键安全反模式

绝不: 未经进程验证进行自动化

# 坏: 无验证
element = uia.find_element_by_name('Password')
element.send_keys(password)

# 好: 全面验证
if validator.validate_process(target_pid):
    if automation.permission_tier != 'read-only':
        element = automation.find_element(process_name, 'Password')
        element.send_keys(password)

绝不: 跳过超时执行

# 坏: 无超时
element = uia.find_element(condition)  # 可能永久挂起

# 好: 带超时
with timeout_mgr.timeout(10):
    element = uia.find_element(condition)

绝不: 允许系统按键组合

# 坏: 允许任何按键
def send_keys(keys):
    SendInput(keys)

# 好: 阻止危险组合
def send_keys(keys):
    if is_blocked_combination(keys):
        raise SecurityError("阻止的按键组合")
    SendInput(keys)

13. 实施前检查清单

阶段 1: 编码前

  • [ ] 阅读 references/threat-model.md 中的威胁模型
  • [ ] 识别目标进程和所需权限层级
  • [ ] 为安全要求编写失败测试
  • [ ] 为预期功能编写失败测试
  • [ ] 为所有操作定义超时限制

阶段 2: 实施期间

  • [ ] 首先实现最少代码通过安全测试
  • [ ] 所有目标交互的进程验证
  • [ ] 配置阻止应用程序列表
  • [ ] 启用权限层级执行
  • [ ] 实现输入速率限制
  • [ ] 所有操作的超时执行
  • [ ] 所有操作的审计日志

阶段 3: 提交前

  • [ ] 所有测试通过: pytest tests/ -v
  • [ ] 安全测试通过: pytest tests/ -k security
  • [ ] 类型检查通过: mypy src/automation --strict
  • [ ] 无硬编码凭据或敏感数据
  • [ ] 审计日志适当配置
  • [ ] 性能目标达成(元素查找 <100ms)

14. 总结

您的目标是创建 Windows UI 自动化,它是:

  • 安全的: 严格的进程验证、权限层级和审计日志
  • 可靠的: 超时执行、错误处理和状态验证
  • 可访问的: 尊重辅助功能 API 和辅助技术

您理解 UI 自动化带来重大安全风险。您平衡自动化能力和严格控制,确保操作被记录、验证和有界。

安全提醒:

  1. 始终验证目标进程身份
  2. 绝不对阻止的安全应用程序进行自动化
  3. 对所有操作执行超时
  4. 使用关联 ID 记录每个操作
  5. 根据风险实施适当的权限层级

自动化应增强生产力,同时维护系统安全边界。


参考资料

  • 高级模式: 见 references/advanced-patterns.md
  • 安全示例: 见 references/security-examples.md
  • 威胁模型: 见 references/threat-model.md