mirror of
https://github.com/PumpkinTTL/kiro-automation-toolkit.git
synced 2026-08-28 17:41:56 +08:00
85efecf0be
🚀 项目特性: - Windows Sandbox 环境支持 - 完整的自动化安装流程 - 智能等待和界面检测机制 - 多种登录方式支持 - 丰富的调试和分析工具 📁 项目结构: - sandbox/ - 项目根目录 - sandbox_files/ - 沙盒环境脚本 - start_sandbox.ps1 - 主启动脚本 - sandbox_config.wsb - Sandbox 配置 🛠️ 核心功能: - 自动化 Kiro IDE 安装 - 登录界面自动化 - 窗口和控件分析 - 详细的进度反馈 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
239 lines
9.6 KiB
Python
239 lines
9.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
快速窗口控件分析器 - 简化版
|
|
专门用于快速分析应用程序控件结构
|
|
"""
|
|
|
|
import time
|
|
import sys
|
|
from pywinauto import Application
|
|
|
|
def quick_analyze(app_path):
|
|
"""快速分析指定应用的窗口控件"""
|
|
|
|
print(f"🔗 连接应用程序: {app_path}")
|
|
|
|
# 特殊处理kiro.exe - 连接到安装界面或应用程序进程
|
|
if "kiro.exe" in app_path.lower():
|
|
print("🔍 检测到kiro.exe,尝试连接进程...")
|
|
|
|
# 扩展的连接方法:支持安装程序和已安装的应用程序
|
|
connection_attempts = [
|
|
# 安装程序连接方法(保留原有功能)
|
|
lambda: Application(backend="uia").connect(title="安装", timeout=5),
|
|
lambda: Application(backend="win32").connect(title="安装", timeout=5),
|
|
lambda: Application(backend="uia").connect(title="安装-Kiro (User)", timeout=5),
|
|
lambda: Application(backend="win32").connect(title="安装-Kiro (User)", timeout=5),
|
|
lambda: Application(backend="uia").connect(title_re=".*安装.*", timeout=5),
|
|
lambda: Application(backend="win32").connect(title_re=".*安装.*", timeout=5),
|
|
lambda: Application(backend="uia").connect(title_re=".*[Ss]etup.*", timeout=5),
|
|
lambda: Application(backend="win32").connect(title_re=".*[Ss]etup.*", timeout=5),
|
|
# 已安装应用程序连接方法(新增功能)
|
|
lambda: Application(backend="uia").connect(title_re=".*Kiro.*", timeout=5),
|
|
lambda: Application(backend="win32").connect(title_re=".*Kiro.*", timeout=5),
|
|
lambda: Application(backend="uia").connect(title_re=".*Getting started.*", timeout=5),
|
|
lambda: Application(backend="win32").connect(title_re=".*Getting started.*", timeout=5),
|
|
lambda: Application(backend="uia").connect(path=app_path, timeout=5),
|
|
lambda: Application(backend="win32").connect(path=app_path, timeout=5),
|
|
]
|
|
|
|
app = None
|
|
for i, attempt in enumerate(connection_attempts, 1):
|
|
try:
|
|
print(f" 尝试方法 {i}...")
|
|
app = attempt()
|
|
print(f"✅ 连接成功! (方法{i}) PID: {app.process}")
|
|
break
|
|
except Exception as e:
|
|
print(f" 方法 {i} 失败: {str(e)[:50]}...")
|
|
continue
|
|
|
|
if not app:
|
|
print("❌ 所有连接方法都失败了")
|
|
return
|
|
else:
|
|
# 原有的连接逻辑
|
|
try:
|
|
app = Application(backend="uia").connect(path=app_path, timeout=10)
|
|
print(f"✅ 连接成功! PID: {app.process}")
|
|
except:
|
|
try:
|
|
app = Application(backend="win32").connect(path=app_path, timeout=10)
|
|
print(f"✅ 连接成功! (Win32模式) PID: {app.process}")
|
|
except Exception as e:
|
|
print(f"❌ 连接失败: {e}")
|
|
return
|
|
|
|
# 等待5秒
|
|
print("⏳ 等待5秒...")
|
|
for i in range(5, 0, -1):
|
|
print(f" {i}秒", end='\r')
|
|
time.sleep(1)
|
|
print(" 完成!")
|
|
|
|
# 获取所有窗口
|
|
print("\n" + "="*60)
|
|
print("🔍 分析窗口控件...")
|
|
print("="*60)
|
|
|
|
try:
|
|
# 尝试多种方式获取窗口
|
|
print("🔍 尝试获取窗口...")
|
|
windows = app.windows()
|
|
print(f"📊 发现 {len(windows)} 个窗口")
|
|
|
|
# 如果没有窗口,尝试其他方法
|
|
if len(windows) == 0:
|
|
print("⚠️ 未发现窗口,尝试其他方法...")
|
|
|
|
# 方法1:尝试获取顶级窗口
|
|
try:
|
|
top_window = app.top_window()
|
|
print(f"✅ 找到顶级窗口: {top_window.window_text()}")
|
|
windows = [top_window]
|
|
except Exception as e:
|
|
print(f"❌ 获取顶级窗口失败: {e}")
|
|
|
|
# 方法2:尝试通过进程ID查找所有窗口
|
|
if len(windows) == 0:
|
|
try:
|
|
from pywinauto import Desktop
|
|
desktop = Desktop(backend="uia")
|
|
all_windows = desktop.windows()
|
|
kiro_windows = []
|
|
for win in all_windows:
|
|
try:
|
|
if win.process_id() == app.process:
|
|
kiro_windows.append(win)
|
|
except:
|
|
continue
|
|
if kiro_windows:
|
|
print(f"✅ 通过进程ID找到 {len(kiro_windows)} 个窗口")
|
|
windows = kiro_windows
|
|
except Exception as e:
|
|
print(f"❌ 通过进程ID查找失败: {e}")
|
|
|
|
print(f"📊 最终发现 {len(windows)} 个窗口\n")
|
|
|
|
for i, window in enumerate(windows, 1):
|
|
try:
|
|
title = window.window_text()
|
|
class_name = window.class_name()
|
|
visible = window.is_visible()
|
|
|
|
print(f"🪟 窗口 {i}: {title or '[无标题]'}")
|
|
print(f" 类名: {class_name}")
|
|
print(f" 可见: {'是' if visible else '否'}")
|
|
|
|
# 分析所有窗口,不管是否可见
|
|
print(" 📋 控件列表:")
|
|
|
|
# 特殊处理InnoSetup窗口
|
|
if "InnoSetup" in title or "InnoSetup" in class_name:
|
|
print(" 🔍 检测到InnoSetup安装程序,尝试激活窗口...")
|
|
try:
|
|
window.set_focus()
|
|
window.restore()
|
|
time.sleep(1) # 等待窗口激活
|
|
print(" ✅ 窗口已激活")
|
|
except Exception as e:
|
|
print(f" ⚠️ 激活窗口失败: {e}")
|
|
|
|
# 获取所有控件
|
|
try:
|
|
controls = window.descendants()
|
|
print(f" 总控件数: {len(controls)}")
|
|
|
|
# 显示前20个有用的控件
|
|
useful_controls = []
|
|
for ctrl in controls:
|
|
try:
|
|
text = ctrl.window_text().strip()
|
|
ctrl_class_name = ctrl.class_name()
|
|
|
|
# 获取UIA属性
|
|
control_type = ""
|
|
automation_id = ""
|
|
if hasattr(ctrl, 'element_info'):
|
|
try:
|
|
control_type = ctrl.element_info.control_type
|
|
automation_id = ctrl.element_info.automation_id or ""
|
|
except:
|
|
pass
|
|
|
|
# 过滤有用的控件 - 放宽条件,显示更多控件
|
|
if (text or automation_id or control_type or
|
|
ctrl_class_name in ['Button', 'Edit', 'ComboBox', 'RadioButton', 'CheckBox', 'Static', 'TButton', 'TEdit'] or
|
|
control_type in ['Button', 'Edit', 'ComboBox', 'RadioButton', 'CheckBox', 'Text', 'Window', 'Pane']):
|
|
|
|
useful_controls.append({
|
|
'text': text or '[无文本]',
|
|
'type': control_type or ctrl_class_name,
|
|
'auto_id': automation_id,
|
|
'class': ctrl_class_name,
|
|
'visible': ctrl.is_visible(),
|
|
'enabled': ctrl.is_enabled()
|
|
})
|
|
|
|
if len(useful_controls) >= 20:
|
|
break
|
|
|
|
except:
|
|
continue
|
|
|
|
# 打印有用的控件
|
|
for j, ctrl_info in enumerate(useful_controls, 1):
|
|
status = []
|
|
if not ctrl_info['visible']:
|
|
status.append("隐藏")
|
|
if not ctrl_info['enabled']:
|
|
status.append("禁用")
|
|
status_str = f" ({', '.join(status)})" if status else ""
|
|
|
|
print(f" {j:2d}. {ctrl_info['text']}{status_str}")
|
|
print(f" 类型: {ctrl_info['type']}")
|
|
if ctrl_info['auto_id']:
|
|
print(f" ID: {ctrl_info['auto_id']}")
|
|
print(f" 类名: {ctrl_info['class']}")
|
|
print()
|
|
|
|
if len(controls) > len(useful_controls):
|
|
print(f" ... 还有 {len(controls) - len(useful_controls)} 个其他控件")
|
|
|
|
except Exception as e:
|
|
print(f" ❌ 获取控件失败: {e}")
|
|
|
|
print("-" * 50)
|
|
|
|
except Exception as e:
|
|
print(f"❌ 分析窗口 {i} 失败: {e}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ 获取窗口失败: {e}")
|
|
|
|
def main():
|
|
"""主函数"""
|
|
print("🚀 快速窗口控件分析器")
|
|
print("="*40)
|
|
|
|
# 获取应用程序路径
|
|
if len(sys.argv) > 1:
|
|
app_path = sys.argv[1]
|
|
else:
|
|
app_path = input("请输入应用程序路径 (例如: kiro.exe): ").strip()
|
|
|
|
if not app_path:
|
|
print("❌ 未提供应用程序路径")
|
|
return
|
|
|
|
quick_analyze(app_path)
|
|
print("\n✅ 分析完成!")
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except KeyboardInterrupt:
|
|
print("\n⚠️ 用户中断")
|
|
except Exception as e:
|
|
print(f"\n❌ 错误: {e}") |