Search

PythonReactSEOPDF
GitHub Skill

gui-control

Управление GUI 1С через X11. Навык учит агента обнаруживать окна 1С (включая диалоги ошибок), делать скриншоты и симулировать ввод (Enter, Escape) для управления интерфейсом без участия человека.

SteelMorgan☆ 22 Repository stars2 Repository forks

Installation

Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.

View source ↗Guides

Skill instructions

Управление 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: Закрыть диалог ошибки и завершить базу

Цель: закрыть базу «естественным путём» после обнаруженного диалога ошибки, чтобы затем анализировать ЖР.

Последовательность клавиш:

  1. Enter — закрыть диалог ошибки.
  2. Escape — инициировать закрытие приложения.
  3. 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: []

Examples

Read the usage examples in the source repository.

View source ↗

Source history

Indexed on
2026-03-11
Index updated
2026-03-11
Branch
main

Index and sync dates describe this directory. View the source repository for code history.

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!