Разработка автоматизированных систем («роботов») на платформе 1С 7.7 часто сопряжена с необходимостью обработки исключительных ситуаций без участия пользователя. Типичный пример: регламентный запрос данных из ЕГАИС, где при возникновении ошибки программист пытается вывести уведомление с помощью функции Предупреждение, задав время автоматического закрытия (таймаут). Однако на практике многие сталкиваются с тем, что окно сообщения «подвисает» на экране неопределенно долго, блокируя выполнение всего алгоритма.
В этой статье мы подробно разберем, почему стандартный механизм таймаута в 1С 7.7 дает сбои, проанализируем влияние внешних компонентов и операционной системы, а также рассмотрим надежные способы обхода этой проблемы.
Рассмотрим ситуацию, когда код обернут в конструкцию Попытка...Исключение, а внутри блока Исключение вызывается Предупреждение с указанием количества секунд:
Попытка
// Основная логика запроса к ЕГАИС
Исключение
Предупреждение("По данной справке нет марок!", 3);
КонецПопытки;
Проанализируем основные факторы, из-за которых это окно может не закрыться через 3 секунды:
ОбработкаОжидания (особенно через внешние компоненты вроде FormEx), возникает конфликт очередей сообщений. Когда модальное окно (которым является Предупреждение) активно, оно запускает свой собственный цикл обработки событий. Если в это время срабатывает таймер, программа может войти в состояние «зацикливания», о чем часто свидетельствует частое «блямканье» системного динамика.Предупреждения замирает до возврата фокуса в программу.Самый простой и надежный способ для роботов — полный отказ от использования модальных окон. Вместо Предупреждение следует использовать Сообщить. Это гарантирует, что выполнение кода не прервется ни при каких обстоятельствах.
Выясним, как лучше модифицировать код, чтобы сохранить информативность для пользователя, если он все-таки решит заглянуть в монитор:
Процедура глПолучитьОтветМарки(ИдЗапроса, УТМ_URL, БезПред = 0) Экспорт
Попытка
// Логика получения данных
Исключение
Если БезПред = 0 Тогда
// Для интерактивной работы
Предупреждение("Ошибка ЕГАИС: " + ОписаниеОшибки(), 3);
Иначе
// Для работы робота
Сообщить("Ошибка ЕГАИС по справке " + СокрЛП(Справка) + ": Нет марок!");
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Если вам критически важно иметь всплывающее окно, которое гарантированно закроется, мы рекомендуем использовать объект WshShell из состава Windows Script Host. Его метод Popup работает гораздо стабильнее встроенного механизма 1С.
Рассмотрим пример реализации:
Процедура глНадежноеПредупреждение(ТекстСообщения, ВремяОжидания = 3)
Попытка
WshShell = СоздатьОбъект("WScript.Shell");
// Параметры Popup: Текст, Таймаут, Заголовок, ТипИконки
WshShell.Popup(ТекстСообщения, ВремяОжидания, "Уведомление системы", 64);
Исключение
// Если WSH недоступен, пишем в окно сообщений
Сообщить(ТекстСообщения);
КонецПопытки;
КонецПроцедуры
Преимущество данного метода: WScript.Shell обрабатывает таймаут на уровне операционной системы, независимо от внутреннего состояния потоков 1С 7.7. Это позволяет избежать «зависаний», характерных для встроенной функции.
Для «автоматических» задач, работающих 24/7 (как в случае с запросами к ЕГАИС раз в 10 минут), лучшим решением будет логирование в файл или специальный справочник. Рассмотрим, как проанализировать ситуацию постфактум, не блокируя работу программы:
ТекстЛога = СоздатьОбъект("Текст");
ТекстЛога.Открыть(КаталогИБ() + "egais_log.txt");
ТекстЛога.ДобавитьСтроку("" + ТекущаяДата() + " " + ТекущееВремя() + ": Справка " + Справка + " - марки отсутствуют.");
ТекстЛога.Записать(КаталогИБ() + "egais_log.txt");
Сообщить("Данные записаны в лог-файл.");
Если вы используете расширение FormEx, проанализируйте, как вызываются ваши функции. Помните следующие правила:
FormEx специальным образом.Предупреждения можно проверять, является ли сессия интерактивной. Если робот запущен под отдельным пользователем, лучше сразу направлять все ошибки в Сообщить или в лог.ОбработкаОжидания пытается выполниться, но блокируется окном. В таком случае использование таймаута в Предупреждении практически бесполезно — конфликт событий не даст таймеру отработать корректно.Подводя итог, можно сказать, что «зависание» таймаута в 1С 7.7 — это комплексная проблема, связанная с устаревшим механизмом обработки оконных сообщений в среде современных ОС и RDP. Для создания отказоустойчивых роботов:
Предупреждение на Сообщить в блоках автоматической обработки.WScript.Shell, если уведомление должно быть всплывающим.Соблюдение этих правил позволит вашим обработкам работать стабильно в течение многих дней без необходимости ручного закрытия «зависших» окон.