«Использование модальных окон в данном режиме запрещено»: откуда берётся и чем лечится

· 9 мин

Содержание

Ошибка Использование модальных окон в данном режиме запрещено не лечится правкой conf.cfg или параметров запуска. Это не настройка клиента, а свойство конфигурации плюс устаревший код, который вызывает окно с ожиданием ответа. Чаще всего помогает одно из двух: заменить модальный вызов на асинхронный или разрешить модальность в свойствах конфигурации, если вы её разработчик.

Ниже по порядку: откуда берётся запрет, как найти строку кода, которая его вызывает, что менять и в каком случае вообще трогать настройки. Статья про платформу 8.3 с интерфейсом «Такси».

Что именно запрещает платформа

Модальное окно останавливает выполнение кода, пока пользователь не нажмёт кнопку. Так работают старые вызовы:

  • Предупреждение() — окно с одной кнопкой «ОК»;
  • Вопрос() — «Да», «Нет», «Отмена»;
  • ВвестиЗначение(), ВвестиСтроку(), ВвестиЧисло(), ВвестиДату() — окно ввода;
  • ОткрытьЗначение(), ОткрытьФормуМодально() — модальное открытие формы;
  • ВыбратьИзСписка(), ВыбратьИзМеню().

Браузеры блокируют такие окна, а мобильный клиент вообще не умеет ждать ответ внутри процедуры. Поэтому разработчики платформы ввели свойство конфигурации «Режим использования модальности». У него три значения:

ЗначениеЧто происходит при вызове Вопрос()
ИспользоватьОкно показывается как раньше
Использовать с предупреждениемОкно показывается, в диагностике появляется предупреждение
Не использоватьВызов обрывается с ошибкой «Использование модальных окон в данном режиме запрещено»

Ошибка возникает при значении «Не использовать». Так настроены современные типовые конфигурации: БП 3.0, ЗУП 3.1, УТ 11 давно переведены на асинхронные вызовы.

Если вы увидели ошибку в типовой конфигурации без доработок, виноват чаще всего внешний отчёт, внешняя обработка или расширение, написанные «по-старому».

Откуда берётся запрет: четыре типичные ситуации

Запрет не появляется сам. Ему предшествует одно из событий:

  1. 🔧 Обновили конфигурацию и режим модальности переключили на «Не использовать». Рабочие раньше внешние обработки перестали открываться.
  2. 📂 Подключили внешнюю обработку или отчёт из старого архива. Код внутри вызывает Вопрос().
  3. 🧩 Поставили расширение, написанное для 8.2 или ранних версий 8.3, без переработки.
  4. 🌐 Перешли на веб-клиент, где модальные окна не работают в принципе, и старый код стал падать.

Для каждого случая лечение своё. Если запрет вызван внешней обработкой, править придётся её, а не конфигурацию.

Как найти строку, которая вызывает ошибку

Пользователь видит только сообщение. Разработчику нужен текст модуля.

Шаг 1. Посмотрите стек вызовов

В окне ошибки нажмите кнопку «Подробно» (в тонком клиенте её название может быть «Информация об ошибке»). Там указан модуль и номер строки: например, Обработка.МояОбработка.Форма.Форма.Форма: {Форма(125)}. Запишите имя модуля и номер строки.

Шаг 2. Откройте модуль в Конфигураторе

Для внешней обработки: Файл → Открыть и выберите .epf. Для конфигурации: откройте нужный объект и его модуль формы. Перейдите на строку из стека.

Шаг 3. Найдите все модальные вызовы сразу

Не ограничивайтесь одной строкой: в том же модуле обычно их несколько. В Конфигураторе есть Правка → Найти в файлах… (в старых версиях — Сервис → Поиск по конфигурации). Ищите по списку:

Предупреждение(
Вопрос(
ВвестиЗначение(
ВвестиСтроку(
ВвестиЧисло(
ВвестиДату(
ОткрытьФормуМодально(
ОткрытьЗначение(
ВыбратьИзСписка(
ВыбратьИзМеню(

Для расширений тот же поиск запускайте по расширению конфигурации.

Режим Предприятия и режим Конфигуратора: чем различается поведение

Разница реально есть, и из-за неё ошибку иногда не удаётся повторить у разработчика.

  • Режим «1С:Предприятие», запущенный из Конфигуратора (отладка): действует то же свойство конфигурации «Режим использования модальности». Если там «Не использовать», запрет сработает так же, как у пользователя.
  • Обычный запуск у пользователя, тонкий клиент: поведение зависит от того же свойства. Дополнительных скрытых флагов в параметрах запуска для этого нет.
  • Веб-клиент: модальные окна не показываются независимо от настройки, потому что браузер их блокирует.

Если у разработчика окно открывается, а у пользователя нет, сначала сравните версию конфигурации и режим совместимости. Копия базы на другом релизе ведёт себя по-другому.

Отладка тоже страдает от модальных вызовов: код ждёт ответа, а окно отладчика остановило выполнение. Это ещё одна причина переписать их на асинхронные.

Что делать: заменить модальные вызовы на асинхронные

Это единственный способ починить, который работает везде: тонкий клиент, веб-клиент, мобильное приложение. Принцип такой: вместо «вызвал и сразу получил ответ» вы передаёте процедуру-обработчик, которую платформа вызовет, когда пользователь ответит.

Предупреждение

Было:

Предупреждение("Документ проведён.");

Стало:

ПоказатьПредупреждение(, "Документ проведён.");

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

Вопрос

Было:

Ответ = Вопрос("Провести документ?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
    ПровестиДокумент();
КонецЕсли;

Стало:

Процедура ПровестиПослеВопроса()
    Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Провести документ?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ПровестиДокумент();
    КонецЕсли;
КонецПроцедуры

Обратите внимание: код, который шёл после Вопрос(), переезжает в процедуру-обработчик. Если оставить его в исходной процедуре, он выполнится, не дожидаясь ответа.

Ввод значений

Для замены ВвестиЗначение(), ВвестиСтроку(), ВвестиЧисло() и ВвестиДату() есть свои асинхронные методы: ПоказатьВводЗначения(), ПоказатьВводСтроки(), ПоказатьВводЧисла(), ПоказатьВводДаты(). Схема та же: описание оповещения, параметры диалога, обработчик с результатом.

Модальное открытие формы

ОткрытьФормуМодально() заменяется на ОткрытьФорму() с параметром режима блокировки окна. Для получения результата выбора передайте описание оповещения последним параметром, а в самой открываемой форме закрывайте её командой Закрыть(Результат).

Если переписывать некогда, а срочно нужно работать: временная мера — разрешить модальность (см. ниже). Но это именно заплатка, а не решение.

Ловушки при переписывании

Асинхронный код ведёт себя иначе, и именно здесь чаще всего ошибаются.

  • Цикл с вопросом внутри. Раньше можно было спрашивать пользователя на каждой итерации. Теперь цикл не остановится: все вопросы появятся одновременно или код пойдёт дальше без ответов. Соберите данные заранее, задайте один вопрос и обработайте результат целиком.
  • Локальные переменные. Обработчик выполняется в другой процедуре и не видит переменные исходной. Нужные значения передавайте третьим параметром ОписаниеОповещения, структурой, и берите в обработчике из ДополнительныеПараметры.
  • Обработчик не экспортный. Процедура оповещения в модуле формы должна быть доступна платформе: ставьте ей Экспорт, иначе вызов не состоится.
  • Директива компиляции. Клиентский обработчик помечайте &НаКлиенте. Если он окажется на сервере, диалог показать будет некому.
  • Код после вызова. Всё, что раньше стояло под Вопрос(), должно уйти в обработчик. Иначе проведение или запись выполнятся до ответа пользователя.

Где и как разрешить модальность, если конфигурация ваша

Это актуально, если вы поддерживаете собственную конфигурацию и сразу переписать код не успеваете.

  1. Откройте базу в Конфигураторе.
  2. Перейдите в свойства корня конфигурации.
  3. Найдите свойство «Режим использования модальности» и выберите «Использовать с предупреждением» (чтобы видеть проблемные места) или «Использовать».
  4. Обновите конфигурацию базы данных, F7.

Для типовой конфигурации на поддержке так делать не стоит: свойство попадёт в «изменённые», а при обновлении возникнет объединение. Лучше исправить код расширением, а не самой конфигурацией.

Выбор в зависимости от обстоятельств:

СитуацияЧто делать
Типовая конфигурация, ошибка во внешней обработкеПереписать обработку
Типовая конфигурация, ошибка в расширенииПереписать расширение
Своя конфигурация, времени малоРежим «Использовать с предупреждением», затем рефакторинг
Веб-клиент или мобильное приложениеТолько переписывание, настройка не поможет

Файл conf.cfg и параметры запуска: почему они не при чём

Многие ищут решение в conf.cfg, потому что видели там правки для платформенных параметров. Но модальность определяется не клиентским конфигурационным файлом и не ключом командной строки 1cv8. Правка conf.cfg ничего не изменит в этой ошибке.

Что можно проверить на стороне клиента:

  • версию платформы: нужна единая версия клиента и сервера в пределах одной ветки;
  • режим запуска: тонкий клиент, толстый или веб. Толстый клиент допускает больше устаревших приёмов, но не отменяет свойство конфигурации;
  • что запускается именно та база, где вы вносили изменения, а не копия.

Если правили conf.cfg по чужому совету и ничего не поменялось, верните файл в исходное состояние: лишние параметры потом мешают при диагностике других проблем.

Диагностика через журнал регистрации

Журнал регистрации помогает понять, у кого и когда падает, особенно если жалуются разные пользователи.

  1. Откройте базу в режиме «1С:Предприятие» под администратором.
  2. Перейдите Администрирование → Поддержка и обслуживание → Журнал регистрации (в зависимости от конфигурации пункт может находиться в разделе администрирования).
  3. Отберите события по уровню «Ошибка» за нужный интервал.
  4. Откройте запись и прочитайте поле «Комментарий»: там текст ошибки и модуль.

Что смотреть:

  • пользователь и компьютер — один человек или все;
  • время — совпадает ли с обновлением конфигурации или подключением новой обработки;
  • приложение — тонкий, веб или фоновое задание: в фоновых заданиях модального диалога не может быть в принципе.

Если ошибка возникает в регламентном или фоновом задании, дело не в настройках: в серверном коде нельзя вызывать ни Вопрос(), ни Предупреждение(). Такой вызов нужно удалить, а сообщения писать в журнал регистрации или выводить через Сообщить().

Мини-кейс: внешняя печатная форма после смены релиза

Бухгалтерия обновила базу, и кнопка печати внешней формы стала выдавать ошибку. Разбор занял немного времени.

  1. В окне ошибки открыли «Подробно»: модуль формы обработки, строка 48.
  2. В Конфигураторе открыли .epf. В строке 48 стоял Ответ = Вопрос("Печатать с факсимиле?", РежимДиалогаВопрос.ДаНет);.
  3. Поиск по модулю нашёл ещё два вызова: Предупреждение() при пустом контрагенте и ВвестиЧисло() для числа копий.
  4. Три места заменили на ПоказатьВопрос(), ПоказатьПредупреждение() и ПоказатьВводЧисла(). Продолжение логики печати вынесли в обработчик оповещения.
  5. Файл сохранили и заново подключили в справочнике внешних обработок.

Итого: три замены и один обработчик. Настройки конфигурации не трогали, и при следующем обновлении ничего не слетело.

Как не словить запрет снова

Запрет возвращается, когда в базу попадает очередная старая обработка. Чтобы этого не было:

  • 📌 перед подключением чужой обработки или расширения ищите в тексте перечень модальных вызовов из списка выше;
  • 📌 тестируйте новые обработки в веб-клиенте: если там работает, то заработает везде;
  • 📌 в собственных разработках не пишите Вопрос() и Предупреждение() даже «временно»: переносить код потом дороже;
  • 📌 храните разработанные расширения и обработки в хранилище или системе контроля версий, чтобы после обновления знать, что и где менять.

Если обработок много и вручную проверять их все не хочется, соберите список подключённых внешних файлов из справочника дополнительных отчётов и обработок и пройдитесь по нему поиском один раз.

Частые сценарии и быстрые решения

Диагностика: выберите симптом

Частые вопросы

Можно ли убрать запрет параметром запуска или в conf.cfg?
Нет. Ограничение задаётся свойством конфигурации, ключи командной строки и файл conf.cfg на него не влияют.
Почему у меня код работал, а после обновления перестал?
Скорее всего, в новой версии конфигурации режим модальности переключён на «Не использовать», а ваша внешняя обработка использует старые вызовы.
Пропадёт ли ошибка, если запустить толстый клиент?
Нет, если запрет задан на уровне конфигурации. Толстый клиент не отменяет свойство «Режим использования модальности».
Нужно ли переписывать всю обработку?
Только места с модальными вызовами. Остальной код остаётся прежним. Обычно хватает замены 3–5 строк и выноса продолжения в отдельную процедуру.
Можно ли обойтись без обработчика оповещения?
Для ПоказатьПредупреждение да, если после закрытия окна ничего делать не нужно. Для вопроса и ввода данных обработчик обязателен: именно он получает ответ.