gui-control
Управление GUI 1С через X11. Навык учит агента обнаруживать окна 1С (включая диалоги ошибок), делать скриншоты и симулировать ввод (Enter, Escape) для управления интерфейсом без участия человека.
Installation
Suivez les instructions du dépôt pour votre agent. Consultez les fichiers et dépendances avant l’installation.
Voir la source ↗GuidesInstructions
Управление GUI 1С через X11
Назначение
Навык учит агента управлять графическим интерфейсом 1С в окружениях с виртуальным X11-дисплеем (Xvfb). Используется когда стандартные инструменты (ЖР, ТЖ) недоступны или недостаточны — например, база «зависла» на диалоге ошибки и не завершается корректно.
Стек:
Xvfb :99 (виртуальный фреймбуфер)
├── python-xlib → читает метаданные окон (заголовки, геометрия), симулирует ввод
└── PIL ImageGrab → читает пиксели фреймбуфера → скриншот
Принцип: X11-управление — это action, не диагностика. Использовать только когда детектирован GUI-диалог, блокирующий нормальное завершение базы. Диагностику причин — через ЖР (event-log-analysis).
Когда применять
| Триггер | Действие |
|---|---|
База запущена, но в ЖР нет событий после test_start_time |
Проверить — не завис ли GUI-диалог |
| Заголовок окна содержит «Ошибка» / «Предупреждение» | Сделать скриншот → закрыть диалог → анализировать ЖР |
| База не завершается после прогона тестов | Закрыть базу естественным путём через Escape + Enter |
| Нужно зафиксировать состояние экрана для лога | Снять скриншот окна 1С |
Настройка окружения
import os
os.environ['DISPLAY'] = ':99'
Переменная должна быть установлена до импорта Xlib и PIL.
Сценарии использования
Сценарий 1: Детектировать диалог ошибки 1С
Цель: проверить, не завис ли GUI на диалоге ошибки, не читая ЖР.
import os
os.environ['DISPLAY'] = ':99'
from Xlib import display
d = display.Display()
root = d.screen().root
error_windows = []
for win in root.query_tree().children:
name = win.get_wm_name()
wm_class = win.get_wm_class()
if wm_class and '1cv8' in wm_class:
if name and any(kw in name for kw in ['Ошибка', 'Предупреждение', 'Error']):
error_windows.append({'id': win.id, 'name': name})
print(error_windows)
Интерпретация:
| Результат | Вывод |
|---|---|
error_windows пустой, есть другие окна 1С |
База работает нормально |
error_windows пустой, нет окон 1С вообще |
База завершилась (успешно или упала до GUI) |
error_windows не пустой |
Диалог ошибки заблокировал выполнение → перейти к сценарию 2 |
Сценарий 2: Закрыть диалог ошибки и завершить базу
Цель: закрыть базу «естественным путём» после обнаруженного диалога ошибки, чтобы затем анализировать ЖР.
Последовательность клавиш:
-
Enter— закрыть диалог ошибки. -
Escape— инициировать закрытие приложения. -
Enter— подтвердить закрытие.
import os, time
os.environ['DISPLAY'] = ':99'
from Xlib import display, X
from Xlib.ext.xtest import fake_input
def send_key(d, keycode, delay=0.3):
fake_input(d, X.KeyPress, keycode)
d.flush()
time.sleep(delay)
fake_input(d, X.KeyRelease, keycode)
d.flush()
time.sleep(delay)
d = display.Display()
ENTER = d.keysym_to_keycode(0xFF0D)
ESCAPE = d.keysym_to_keycode(0xFF1B)
send_key(d, ENTER) # закрыть диалог ошибки
time.sleep(1)
send_key(d, ESCAPE) # инициировать закрытие
time.sleep(1)
send_key(d, ENTER) # подтвердить закрытие
Важно: после выполнения подождать 2–3 секунды и проверить через сценарий 1, что окон 1С больше нет.
Сценарий 3: Скриншот для лога
Цель: зафиксировать состояние экрана перед закрытием диалога ошибки.
Когда нужен: только для лога или ручной отладки. В автоматическом пайплайне — опционально, перед шагом 2.
import os
os.environ['DISPLAY'] = ':99'
from PIL import ImageGrab
from Xlib import display
d = display.Display()
root = d.screen().root
for win in root.query_tree().children:
name = win.get_wm_name()
wm_class = win.get_wm_class()
if wm_class and '1cv8' in wm_class:
geom = win.get_geometry()
img = ImageGrab.grab(bbox=(
geom.x, geom.y,
geom.x + geom.width,
geom.y + geom.height
))
path = f'/tmp/onec_{win.id}.png'
img.save(path)
print(f'Скриншот сохранён: {path}')
Типичный пайплайн: тесты завершились, база не закрылась
1. search_event_log(from=test_start_time, limit=20)
│
├── есть события, нет Error → база работает, ждать
├── есть Error → скриншот (сценарий 3) → закрыть (сценарий 2) → анализ ЖР
└── нет событий → детектировать окна (сценарий 1)
│
├── окно с ошибкой → скриншот → закрыть
└── нет окон → база не запустилась
Безопасность
| Правило | Описание |
|---|---|
| Только локально | X11-управление работает только в окружении с Xvfb. Не применять на продуктивных серверах с реальным дисплеем. |
| Enter/Escape — не произвольный ввод | Симулировать только навигационные клавиши. Не вводить данные в поля формы. |
| Скриншоты — в /tmp/ | Не сохранять в репозиторий. Скриншоты могут содержать персональные данные из форм 1С. |
Типичные ошибки
| Ошибка | Обходной путь |
|---|---|
DISPLAY не установлен |
os.environ['DISPLAY'] = ':99' до импортов |
python-xlib не установлен |
pip install python-xlib |
PIL.ImageGrab не работает на Linux |
Использовать Pillow + python3-xlib: pip install Pillow |
| Окна 1С не найдены, но процесс есть | Процесс запустился, но GUI ещё не отрисован — подождать 2–3 сек и повторить |
| XTEST extension недоступна | Проверить что Xvfb запущен с флагом -extensions XTEST |
Capabilities
| Capability | Назначение |
|---|---|
python-xlib |
Чтение метаданных окон, симуляция ввода |
PIL ImageGrab |
Скриншот фреймбуфера или отдельного окна |
Связанные навыки
| Навык | Когда использовать |
|---|---|
event-log-analysis |
Анализ причин ошибки после закрытия диалога |
tech-log-analysis |
Технические детали (СУБД, блокировки) если ЖР не даёт ответа |
depends_on: []
Exemples
Consultez les exemples du dépôt source.
Voir la source ↗Historique source
- Date d’indexation
- 2026-03-11
- Mise à jour de l’index
- 2026-03-11
- Branch
- main
Les dates concernent ce répertoire. Consultez le dépôt pour l’historique du code.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!