Внешняя обработка или печатная форма не работает после обновления 1С: что пропало и как проверить заранее
Иван Недомолков · Жарияланды:
Типовую обновили, конфигуратор ни на что не пожаловался, база открылась. А потом звонит бухгалтер: внешняя печатная форма счёта больше не печатается. Или ночной обмен с сайтом, который запускается снаружи, перестал выгружать заказы. Код обработки никто не трогал, файл тот же.
Причина почти всегда одна: обработка зовёт метод общего модуля, документ или справочник, которого в новом релизе под этим именем больше нет. Внешняя обработка не входит в конфигурацию, поэтому при обновлении её не проверяет никто. Ниже разбор по тексту ошибки, объяснение, где именно пропадает сигнал, и порядок проверки, который стоит пройти до следующего обновления.
Что означает текст ошибки
Первое, что стоит сделать, это прочитать текст ошибки дословно. По нему сразу понятно, что пропало в новом релизе и в какой момент обработка должна была упасть.
| Текст ошибки | Что пропало | Когда проявляется |
|---|---|---|
| ”Переменная не определена (ИмяМодуля)“ | общий модуль целиком | при открытии обработки, она не открывается совсем |
| ”Метод объекта не обнаружен (ИмяМетода)“ | метод из модуля, который сам остался | на строке с вызовом, когда до неё дошло исполнение |
| ”Слишком много фактических параметров” | у метода стало меньше параметров | на строке с вызовом |
| ”Поле объекта не обнаружено (ИмяОбъекта)“ | документ, справочник, регистр, перечисление | на строке с обращением к менеджеру |
Разница между первой строкой и остальными тремя принципиальная. Пропавший модуль компилятор ловит сразу: имя модуля для него превращается в необъявленную переменную, и форма не откроется. Всё остальное компилятор пропускает. Вызов метода общего модуля и обращение к менеджеру объекта по имени платформа разрешает только тогда, когда исполняет строку. Обработка откроется и может отработать не один раз. Упадёт она в той ветке кода, куда вызов спрятан. Если это ветка для редкого вида операции, поломку найдут через месяц.
Эти четыре случая легко воспроизвести на любой базе с БСП. Условие Если Ложь не даёт строке исполниться, поэтому видно только, что скажет компилятор:
// Выполняется в любой базе на БСП, конфигурацию не меняет.
// "Если Ложь" - строка не исполнится, смотрим только на компиляцию.
// Модуля нет: ошибка компиляции "Переменная не определена (МодульКоторогоНет)".
Выполнить("Если Ложь Тогда Ж = МодульКоторогоНет.Метод(); КонецЕсли;");
// Модуль есть, метода нет: компилируется без замечаний.
Выполнить("Если Ложь Тогда ОбщегоНазначения.НетТакого(1); КонецЕсли;");
// Параметров у метода пять (так в УТ 11.5), передаём восемь: тоже компилируется.
Выполнить("Если Ложь Тогда ОбщегоНазначенияКлиентСервер.СообщитьПользователю(1,2,3,4,5,6,7,8); КонецЕсли;");
// Документа нет: тоже компилируется.
Выполнить("Если Ложь Тогда Д = Документы.НетТакогоДокумента.СоздатьДокумент(); КонецЕсли;");
Мы гоняли этот фрагмент на УТ 11.5, платформа 8.3.27. Уберите Если Ложь, и три последние строки упадут ровно с теми текстами, что стоят в таблице. Компиляция от конфигурации не зависит, это поведение платформы, а общие модули ОбщегоНазначения и ОбщегоНазначенияКлиентСервер есть в любой конфигурации на БСП.
Где теряется сигнал: кто что проверяет
Почему ни один штатный механизм об этом не предупредил? Мы прошли их по очереди.
| Механизм | Что проверяет | Видит внешнюю обработку |
|---|---|---|
| Сравнение-объединение и обновление конфигурации БД | объекты и модули самой конфигурации | нет: для него файл обработки или строка справочника “Дополнительные отчёты и обработки” это данные, как картинка в присоединённом файле |
Пакетная проверка модулей /CheckModules | модули конфигурации базы | нет: ключа для внешних обработок у неё нет, незнакомый ключ платформа молча пропускает и отвечает “Синтаксических ошибок не обнаружено!” |
| Открытие обработки пользователем | компиляция модулей | да, но ловит только пропавший модуль целиком |
| Живые метаданные базы | есть ли общий модуль, документ, справочник | видит объекты, но не знает, какие экспортные методы внутри модуля и сколько у них параметров |
Про /CheckModules отдельно. Мы проверили это на своей обработке с заведомо битым кодом: Если Тогда без условия плюс необъявленная переменная. Две базы ответили тем же зелёным сообщением. Проверка ошибку не пропустила, она на этот файл просто не смотрела.
Из таблицы следует главное. Про методы внутри общих модулей знает только текст этих модулей, то есть выгрузка конфигурации в файлы. Сверять вызовы обработки придётся с выгрузкой нового релиза, других источников нет.
Сколько может сломаться: худший случай в цифрах
Чтобы понять масштаб, мы взяли переход с максимальной разницей: две типовые поставки УТ для Казахстана, 2.2.16.5 и 3.4.4.87. Оговорка обязательна. Это смена редакции с переносом данных в новую базу, обычным обновлением её никто не делает. Редакция 2.2 работает как обычное приложение в режиме совместимости 8.2, 3.4 управляемая и построена на БСП. Мы брали этот переход как худший случай: здесь видно всё, что вообще может сломаться. Механизм молчания при этом тот же, что у любого обновления.
Программный интерфейс общих модулей, экспортные методы 2.2.16.5 против 3.4.4.87:
| Что стало с методом | Методов |
|---|---|
| Всего экспортных методов в 120 общих модулях 2.2.16.5 | 2 839 |
| Ушли вместе с модулем (51 модуль исчез целиком) | 1 214 |
| Пропали из модуля, который по имени остался | 710 |
| Число параметров сузилось | 55 |
| Перестали быть экспортными | 9 |
| Дожили без изменений | 851 (30,0 %) |
“Без изменений” значит: метод в 3.4.4.87 есть, он экспортный, и старый вызов подходит к нему по числу параметров. У модулей менеджеров картина похожая: из 109 экспортных методов в 15 модулях без изменений 45.
Самая неприятная строка тут вторая сверху. Модуль ОбщегоНазначения в 3.4 на месте, и в коде обработки его имя выглядит живым. Но из 321 экспортного метода, которые были в нём в 2.2.16.5, в 3.4.4.87 нет 219. Это тот самый случай “Метод объекта не обнаружен”: обработка откроется и упадёт на строке.
Дальше мы прогнали по этим двум поставкам настоящую внешнюю обработку обмена с сайтом от стороннего разработчика, написанную под УТ на обычных формах 8.2, вместе с тремя файлами её комплекта.
| Результат по 79 вызовам типовой (46 разных методов и объектов) | Вызовов |
|---|---|
| Сломается при переходе | 33 |
| из них: объекта метаданных в 3.4 нет | 26 |
| из них: общего модуля нет целиком | 4 |
| из них: модуль есть, метода нет | 3 |
| из них: метод стал неэкспортным или не сошлось число параметров | 0 |
| Не работает уже на 2.2.16.5 | 9 |
| В порядке | 37 |
Мы ждали, что главной бедой будут сигнатуры. На этой обработке проверка числа параметров не сработала ни разу. При смене поколения меняется состав конфигурации: документа или регистра, в который обработка писала, под этим именем больше нет.
Девять вызовов, сломанных ещё до перехода, тоже показательны. Четыре из них Перечисления.СтавкиНДС: такого перечисления в УТ для Казахстана 2.2 нет, обработка писалась и под российскую УТ. Остальные пять обращаются к объектам её собственного комплекта, которых в типовой нет. В этой базе такие ветки кода не работали никогда.
Обратный пример дали наши собственные 42 обработки, написанные под БСП. Вызовов типовой на все 42 набралось всего 14, но 13 из них на 2.2.16.5 не работали бы. Семь приходятся на модули ДополнительныеОтчетыИОбработки*, то есть на функцию регистрации дополнительной обработки. Даже простая дополнительная обработка под БСП привязана к конфигурации раньше, чем начинается её собственная логика.
Порядок проверки до обновления
- Собрать список. Внешние обработки и печатные формы живут в двух местах: в справочнике “Дополнительные отчёты и обработки” и файлами
.epfи.erfна дисках. Проверять надо оба. - Выгрузить текущую конфигурацию в файлы. Полная выгрузка подойдёт, но можно выгрузить только объекты, которые обработки вызывают. На УТ 11.5 частичная выгрузка 12 объектов пакетным конфигуратором заняла 14 секунд.
- Выгрузить новый релиз из копии своей базы после сравнения-объединения. Чистый шаблон поставки для этого не годится: ваших доработок в нём нет. Если обработка зовёт доработанный объект, по шаблону этот вызов выглядит сломанным, хотя при нормальном обновлении доработка переедет и вызов останется рабочим.
- Сверить каждый вызов общего модуля и менеджера с обеими выгрузками: есть ли метод, экспортный ли он, подходит ли число параметров, на месте ли объект.
- Разобрать результат начиная со сломанного в новом релизе.
Если текущая база в режиме совместимости 8.2, как УТ 2.2, наша обработка в ней не скомпилируется: “Переменная не определена (НаправлениеПоиска)”, режим совместимости прячет всё, что появилось в 8.3. Обход мы проверили прогоном: запускать проверку в любой современной базе, хоть в копии нового релиза, и давать обе выгрузки файлами.
Шаги 4 и 5 мы собрали в обработку проверки внешних обработок при обновлении типовой, описание и границы на её странице в разделе инструментов. Она распаковывает .epf и .erf без конфигуратора и ставит каждому вызову один из четырёх статусов. Что с каждым делать:
| Статус | Что значит | Что делать |
|---|---|---|
| СЛОМАЕТСЯ | в выгрузке нового релиза нет метода или объекта, метод не экспортный, не сходится число параметров | чинить до переноса, начиная с самых частых вызовов |
| УЖЕ СЛОМАНО | не работает и в текущей конфигурации | к обновлению отношения не имеет: ветка кода мёртвая, либо обработка писалась под другую конфигурацию |
| НЕ ПРОВЕРЕНО | нет выгрузки или вызов идёт в объект расширения | дать выгрузку; объекты расширений проверять отдельно |
| ОК | метод и объект на месте, параметры подходят | ничего |
Четыре файла комплекта обработки обмена сверялись 1,7 секунды, весь прогон с подключением к базе занял около 11 секунд.
Если сверять вручную: две ловушки
Сверку можно сделать и без инструмента: выгрузить обработку в файлы, выписать вызовы общих модулей и менеджеров, а потом искать в выгрузке нового релиза объявление каждого метода со словом Экспорт и считать параметры в скобках. В ручной сверке есть два места, где легко насчитать поломок больше, чем их есть.
Методы коллекции выглядят как объекты. В ПланыОбмена.ВыбратьИзменения(...) или Документы.ТипВсеСсылки() второе слово не имя объекта, это метод самой коллекции менеджеров. Первая версия нашей проверки искала объект с именем ВыбратьИзменения и писала “нет объекта”. На обработках под 2.2 это дало 13 ложных строк: 92 вызова до правки, 79 после. Правило простое: объект метаданных скобками не вызывается, значит конструкция “Коллекция.Имя(” это метод коллекции.
Локальная переменная с именем общего модуля. Если в коде написано Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей(), дальше Пользователи.Количество() к общему модулю Пользователи отношения не имеет. На наших 42 обработках такое совпадение дало 3 ложные находки, пока проверка не начала собирать имена переменных и параметров по каждому методу. Реквизит формы с именем общего модуля она по-прежнему от модуля не отличает, и при ручной сверке его тоже стоит проверять глазами.
Замена по имени не всегда замена по смыслу
Когда поломка найдена, хочется просто подставить новое имя. Вот что стоит на месте вызовов нашей обработки обмена в 3.4.4.87:
| Вызов в 2.2.16.5 | В 3.4.4.87 | Что там вместо |
|---|---|---|
ОбщегоНазначения.СообщитьОбОшибке | нет метода | ОбщегоНазначенияКлиентСервер.СообщитьПользователю |
ЗаполнениеДокументов.ЗаполнитьШапкуДокумента | нет модуля | модуля нет целиком |
Документы.ЗаказПокупателя.СоздатьДокумент() | нет объекта | документ ЗаказКлиента |
Справочники.КонтактныеЛицаКонтрагентов.СоздатьЭлемент() | нет объекта | справочник КонтактныеЛицаПартнеров |
РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей() | нет объекта | табличная часть КонтактнаяИнформация у объектов, модуль УправлениеКонтактнойИнформацией |
ПланыВидовХарактеристик.СвойстваОбъектов | нет объекта | ДополнительныеРеквизитыИСведения |
Первая строка выглядит самой безобидной. Мы открыли обе процедуры в выгрузках. Старая, 2.2.16.5 (сокращено):
// УТ для Казахстана 2.2.16.5, общий модуль ОбщегоНазначения
Процедура СообщитьОбОшибке(ТекстСообщения, Отказ = Ложь, Заголовок = "",Статус = Неопределено) Экспорт
// ...
Отказ = Истина;
#Если ВнешнееСоединение Тогда
// ...
ВызватьИсключение (ТекстСообщения);
#Иначе
// ...
Сообщить(ТекстСообщения, Статус);
#КонецЕсли
КонецПроцедуры
Новая, 3.4.4.87:
// УТ для Казахстана 3.4.4.87, общий модуль ОбщегоНазначенияКлиентСервер
Процедура СообщитьПользователю(
Знач ТекстСообщенияПользователю,
Знач КлючДанных = Неопределено,
Знач Поле = "",
Знач ПутьКДанным = "",
Отказ = Ложь) Экспорт
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстСообщенияПользователю;
// ...
Сообщение.Сообщить();
Отказ = Истина;
КонецПроцедуры
Под внешним соединением старая процедура бросала исключение, и обмен, запущенный снаружи, останавливался с понятным текстом. Новая пишет сообщение, которое под внешним соединением никто не прочитает, и код идёт дальше. После простой замены имени обработка скомпилируется и отработает, только ошибки обмена станут невидимыми. Второй параметр тоже разъехался: раньше вторым шёл Отказ, теперь там КлючДанных, а Отказ переехал на пятое место. Старый код, передававший Отказ вторым параметром, после переименования отправит булево туда, где ждут ссылку.
С объектами ещё строже. ЗаказКлиента занимает место ЗаказПокупателя, но реквизиты и логика заполнения у него свои, а контактная информация из регистра сведений переехала в табличные части объектов. Поэтому автозамены проверка и не предлагает: чем заменить вызов, решает тот, кто знает, что обработка должна делать.
Чего сверка вызовов не увидит
Проверка статическая, код обработок читается без исполнения. Отсюда границы, которые стоит держать в голове.
- Вызовы, собранные строкой.
Выполнить(...),ОбщегоНазначения.ОбщийМодуль("Имя")и всё, что складывается текстом во время работы. Такие обработки после сверки всё равно стоит прогнать на копии. - Методы объекта в переменной. Сверяются вызовы общих модулей и менеджеров вида
Документы.Имя.Метод(). Вызов метода у объекта документа, полученного в переменную, в сверку не попадает. - Смысл замены. Случай с
СообщитьОбОшибкепроверка покажет как “нет метода”. Что у замены другое поведение, видно только в коде обеих редакций. - Расширения. Объекты расширений получают НЕ ПРОВЕРЕНО: в выгрузке типового релиза их нет и быть не должно. Применимость самих расширений после обновления это отдельная проверка.
- Где гоняли. Платформа 8.3.27, серверные базы, поставки УТ для Казахстана 2.2.16.5 и 3.4.4.87 и УТ 11.5. Конфигурации без БСП, файловые базы, веб-клиент и Linux-сервер не проверялись.
Если вместе с конфигурацией меняется и платформа, к списку добавляются изменения самой 8.5: их мы разобрали в статье про подготовку к переходу на 1С 8.5. А качество кода тех же обработок, запросы в цикле и запись без проверок, смотрит другая проверка: анализ кода внешних обработок и анализатор кода 1С.
Между соседними релизами мы пока не мерили
Переход с 2.2 на 3.4 это потолок: 33 сломанных вызова из 79 у одной обработки. Сколько ломается при обычном обновлении внутри одной редакции, между соседними релизами типовой, мы на чистых типовых поставках не считали, и придумывать цифру не будем. Порядок проверки там тот же. Если прогоните свои обработки перед ближайшим обновлением, напишите нам, что оказалось чаще: пропавшие объекты или пропавшие методы общих модулей.