Почему функция Предупреждение с таймаутом не закрывается автоматически в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Разработка автоматизированных систем («роботов») на платформе 1С 7.7 часто сопряжена с необходимостью обработки исключительных ситуаций без участия пользователя. Типичный пример: регламентный запрос данных из ЕГАИС, где при возникновении ошибки программист пытается вывести уведомление с помощью функции Предупреждение, задав время автоматического закрытия (таймаут). Однако на практике многие сталкиваются с тем, что окно сообщения «подвисает» на экране неопределенно долго, блокируя выполнение всего алгоритма.

В этой статье мы подробно разберем, почему стандартный механизм таймаута в 1С 7.7 дает сбои, проанализируем влияние внешних компонентов и операционной системы, а также рассмотрим надежные способы обхода этой проблемы.

Причины некорректного поведения таймаута

Рассмотрим ситуацию, когда код обернут в конструкцию Попытка...Исключение, а внутри блока Исключение вызывается Предупреждение с указанием количества секунд:


Попытка
    // Основная логика запроса к ЕГАИС
Исключение
    Предупреждение("По данной справке нет марок!", 3);
КонецПопытки;

Проанализируем основные факторы, из-за которых это окно может не закрыться через 3 секунды:

  1. Баг платформы (движка bkend.dll): В 1С 7.7 механизм отсчета времени в модальных окнах реализован через системные таймеры Windows. Если в момент вызова окна фокус приложения теряется или происходит перехват управления другим процессом, внутренний счетчик может «сброситься» или встать на паузу.
  2. Конфликт с обработками ожидания: Если в конфигурации активно используются ОбработкаОжидания (особенно через внешние компоненты вроде FormEx), возникает конфликт очередей сообщений. Когда модальное окно (которым является Предупреждение) активно, оно запускает свой собственный цикл обработки событий. Если в это время срабатывает таймер, программа может войти в состояние «зацикливания», о чем часто свидетельствует частое «блямканье» системного динамика.
  3. Работа в терминальной сессии (RDP): Это одна из самых частых причин. Если пользователь закрыл окно RDP-клиента (не завершив сеанс) или произошло временное отключение сети, графическая подсистема Windows перестает корректно отрисовывать модальные окна. Таймер таймаута в 1С 7.7 может просто не инициализироваться, так как система считает окно «невидимым» или неактивным.
  4. Потеря фокуса: Если во время работы робота на сервере или локальном ПК всплывает другое окно (например, обновление антивируса или системное уведомление), фокус уходит с 1С. В некоторых сборках 1С 7.7 это приводит к тому, что таймер Предупреждения замирает до возврата фокуса в программу.

Решение №1: Использование метода Сообщить()

Самый простой и надежный способ для роботов — полный отказ от использования модальных окон. Вместо Предупреждение следует использовать Сообщить. Это гарантирует, что выполнение кода не прервется ни при каких обстоятельствах.

Выясним, как лучше модифицировать код, чтобы сохранить информативность для пользователя, если он все-таки решит заглянуть в монитор:


Процедура глПолучитьОтветМарки(ИдЗапроса, УТМ_URL, БезПред = 0) Экспорт
    Попытка 
        // Логика получения данных
    Исключение
        Если БезПред = 0 Тогда
            // Для интерактивной работы
            Предупреждение("Ошибка ЕГАИС: " + ОписаниеОшибки(), 3);
        Иначе
            // Для работы робота
            Сообщить("Ошибка ЕГАИС по справке " + СокрЛП(Справка) + ": Нет марок!");
        КонецЕсли;
    КонецПопытки;
КонецПроцедуры

Решение №2: Использование системного объекта WScript.Shell

Если вам критически важно иметь всплывающее окно, которое гарантированно закроется, мы рекомендуем использовать объект WshShell из состава Windows Script Host. Его метод Popup работает гораздо стабильнее встроенного механизма 1С.

Рассмотрим пример реализации:


Процедура глНадежноеПредупреждение(ТекстСообщения, ВремяОжидания = 3)
    Попытка
        WshShell = СоздатьОбъект("WScript.Shell");
        // Параметры Popup: Текст, Таймаут, Заголовок, ТипИконки
        WshShell.Popup(ТекстСообщения, ВремяОжидания, "Уведомление системы", 64);
    Исключение
        // Если WSH недоступен, пишем в окно сообщений
        Сообщить(ТекстСообщения);
    КонецПопытки;
КонецПроцедуры

Преимущество данного метода: WScript.Shell обрабатывает таймаут на уровне операционной системы, независимо от внутреннего состояния потоков 1С 7.7. Это позволяет избежать «зависаний», характерных для встроенной функции.

Решение №3: Запись логов в текстовый файл

Для «автоматических» задач, работающих 24/7 (как в случае с запросами к ЕГАИС раз в 10 минут), лучшим решением будет логирование в файл или специальный справочник. Рассмотрим, как проанализировать ситуацию постфактум, не блокируя работу программы:


ТекстЛога = СоздатьОбъект("Текст");
ТекстЛога.Открыть(КаталогИБ() + "egais_log.txt");
ТекстЛога.ДобавитьСтроку("" + ТекущаяДата() + " " + ТекущееВремя() + ": Справка " + Справка + " - марки отсутствуют.");
ТекстЛога.Записать(КаталогИБ() + "egais_log.txt");
Сообщить("Данные записаны в лог-файл.");

Рекомендации по работе с FormEx и обработками ожидания

Если вы используете расширение FormEx, проанализируйте, как вызываются ваши функции. Помните следующие правила:

Итоги анализа

Подводя итог, можно сказать, что «зависание» таймаута в 1С 7.7 — это комплексная проблема, связанная с устаревшим механизмом обработки оконных сообщений в среде современных ОС и RDP. Для создания отказоустойчивых роботов:

  1. Замените Предупреждение на Сообщить в блоках автоматической обработки.
  2. Используйте WScript.Shell, если уведомление должно быть всплывающим.
  3. Организуйте полноценное логирование ошибок в файл или табло, чтобы работа не прерывалась из-за одной некорректной справки ЕГАИС.

Соблюдение этих правил позволит вашим обработкам работать стабильно в течение многих дней без необходимости ручного закрытия «зависших» окон.

← На главную