Что изменилось под расширением: проверка заимствованных объектов перед обновлением 1С

· 10 мин

Содержание

Сравнить конфигурацию и расширение в 1С 8.3 можно тремя способами. Быстро — командой проверки применимости расширений в Конфигураторе: она сразу скажет, встанет ли расширение на новую основную конфигурацию. Точно — выгрузкой конфигурации и расширения в XML (Конфигурация → Выгрузить конфигурацию в файлы) с последующим сравнением в WinMerge или git diff. Регулярно — скриптом на OneScript, который делает выгрузку и сравнение без участия человека.

Первый способ подходит, когда нужно ответить «да или нет» перед обновлением. Второй — когда надо понять, что именно поменялось в объектах, которые расширение заимствует. Третий — когда расширений много, а обновления идут каждый месяц.

Почему расширение не видно в обычном сравнении конфигураций

Расширение хранится в базе отдельно от основной конфигурации. Окно Конфигурация → Сравнить конфигурации в дереве основной конфигурации работает только с ней, с конфигурацией поставщика и с файлами .cf. Объекты расширения там не появляются, даже если они заимствованы из этой самой конфигурации.

Причина в устройстве механизма. Расширение не копирует объект, а ссылается на него:

  • 🔗 заимствованный объект — ссылка на объект основной конфигурации по его внутреннему идентификатору плюс набор контролируемых свойств;
  • 🧩 собственный объект — новый справочник, реквизит, форма или модуль, которого в основной конфигурации нет;
  • ✏️ перехват метода — процедура с аннотацией &Перед, &После, &Вместо или &ИзменениеИКонтроль, которая подменяет или дополняет код основной конфигурации.

Поэтому вопрос «чем расширение отличается от конфигурации» на практике распадается на два. Совпадают ли заимствованные объекты с тем, что сейчас лежит в основной конфигурации? И какие объекты основной конфигурации поменялись после обновления так, что расширение перестанет подключаться или начнёт работать неправильно?

Расширения появились в платформе 8.3.6. Аннотация &ИзменениеИКонтроль — позже, поэтому в старых базах на устаревших платформах её нет. Если у вас платформа 8.3.2x, доступны все описанные ниже приёмы.

Способы сравнения: что выбрать под вашу задачу

СпособКогда подходитЧто показываетОграничения
Проверка применимости в КонфигуратореПеред обновлением основной конфигурацииВстанет ли расширение, и на каком объекте ошибкаНе показывает изменения, которые не ломают подключение
Сравнение расширения с файлом .cfeДве версии одного расширенияРазличия объектов, свойств и модулейСопоставляет объекты по внутренним идентификаторам
Выгрузка в XML и внешний diffНужно увидеть конкретные строки кода и свойстваВсё, построчноНужно место на диске и инструмент сравнения
Скрипт на OneScriptМного баз и расширений, регулярные обновленияСписок заимствованных объектов, которые поменялисьНужна настройка один раз

Для разовой проверки небольшого расширения хватит первых двух строк таблицы. Для расширения на 30–50 заимствованных объектов удобнее XML: глазами по дереву Конфигуратора это не просмотреть.

Сравнение расширения с конфигурацией в Конфигураторе

Открыть дерево расширения

  1. Запустите Конфигуратор под пользователем с правами администратора.
  2. Выберите Конфигурация → Расширения конфигурации. Откроется список расширений базы.
  3. Дважды щёлкните нужное расширение — откроется его дерево объектов в отдельном окне.

В дереве заимствованные объекты отмечены особым значком, а собственные выглядят как обычные. Откройте свойства заимствованного объекта: в палитре свойств у части полей есть отметка контроля. Именно эти свойства платформа сверяет с основной конфигурацией при подключении расширения.

Проверить применимость

В окне списка расширений есть команда проверки применимости. Она прогоняет все расширения против текущей основной конфигурации и выводит список проблем: объект удалён, у контролируемого свойства другое значение, изменился текст метода под &ИзменениеИКонтроль.

Правильный порядок при обновлении такой:

  1. Сделайте копию базы и обновите основную конфигурацию в копии.
  2. Выполните Конфигурация → Обновить конфигурацию базы данных.
  3. Запустите проверку применимости расширений.
  4. Для каждого сообщения откройте объект в дереве расширения и исправьте его.
  5. Сохраните исправленное расширение и обновите его в базе отдельно от основной конфигурации.

Загрузка .cfe и обновление конфигурации базы данных — это разные шаги. Загрузили расширение из файла и не обновили его — в режиме предприятия будет работать старая версия.

Обновить заимствованные объекты

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

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

Методы с &ИзменениеИКонтроль

Этот перехват хранит копию исходного текста метода с вставками #Вставка … #КонецВставки и удалениями #Удаление … #КонецУдаления. Если в основной конфигурации текст метода поменялся хотя бы на строку, расширение не подключится.

Исправлять такой метод вручную долго. Быстрее скопировать новый текст метода из основной конфигурации в модуль расширения и заново расставить свои вставки. Старую версию держите рядом в соседнем окне или в XML-выгрузке.

Выгрузка конфигурации и расширения в XML для внешнего сравнения

Встроенного окна, где основная конфигурация и расширение лежат рядом, нет. Зато обе можно выгрузить в файлы с одинаковой структурой каталогов и сравнить любым инструментом.

Выгрузка из Конфигуратора

  • Основная конфигурация: в дереве основной конфигурации Конфигурация → Выгрузить конфигурацию в файлы.
  • Расширение: та же команда, но вызванная из окна дерева расширения.

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

Выгрузка из командной строки

Пакетный режим Конфигуратора делает то же без открытия окон:

set V8="C:\Program Files\1cv8\8.3.xx.xxxx\bin\1cv8.exe"
set BASE=/F "D:\Bases\Buh_copy"
set AUTH=/N "Администратор" /P ""

rem Основная конфигурация
%V8% DESIGNER %BASE% %AUTH% /DumpConfigToFiles "D:\dump\main" /Out "D:\dump\main.log"

rem Расширение
%V8% DESIGNER %BASE% %AUTH% /DumpConfigToFiles "D:\dump\ext" -Extension "МоеРасширение" /Out "D:\dump\ext.log"

rem Расширение в файл .cfe
%V8% DESIGNER %BASE% %AUTH% /DumpCfg "D:\dump\МоеРасширение.cfe" -Extension "МоеРасширение"

Для серверной базы вместо /F укажите /S "сервер\имябазы". Номер платформы в пути замените на свой. Ошибки выгрузки смотрите в файле, указанном в /Out: пакетный режим окон с ошибками не показывает.

Как читать XML расширения

Заимствованный объект в выгрузке расширения узнаётся по строке <ObjectBelonging>Adopted</ObjectBelonging> в его XML-файле. У собственных объектов такой строки нет. Модули лежат рядом в файлах .bsl, формы — в подкаталогах Forms.

Пути в выгрузке расширения совпадают с путями в выгрузке основной конфигурации: Catalogs\Номенклатура.xml есть и там, и там. Это и даёт возможность сравнивать объект «из расширения» с тем же объектом «из конфигурации».

Для сравнения подойдут:

  • 🖥 WinMerge — бесплатный, сравнивает каталоги целиком и подсвечивает строки;
  • 🧮 Beyond Compare — платный, удобные фильтры по маскам файлов;
  • 🌿 git diff --no-index D:\dump\old D:\dump\new — без установки лишнего, если Git уже стоит.

Самый полезный сценарий — не «расширение против конфигурации», а «старая основная конфигурация против новой», отфильтрованное по списку заимствованных объектов. Так видно, какие из объектов под расширением тронуло обновление.

Сравнение двух версий расширения: где ловушки

Сравнить две версии одного расширения проще всего в Конфигураторе. В окне дерева расширения выберите Конфигурация → Сравнить, объединить с конфигурацией из файла и укажите файл .cfe. Откроется знакомое окно сравнения и объединения с галочками по объектам.

Здесь несколько ловушек.

🔑 Идентификаторы объектов. Платформа сопоставляет объекты не по имени, а по внутреннему идентификатору. Если разработчик пересоздал расширение с нуля и заново заимствовал те же объекты, у них будут другие идентификаторы. Сравнение покажет «всё удалено и всё добавлено», хотя по сути изменилось два модуля. В этом случае сравнивайте XML-выгрузки: имена файлов совпадут.

🏷 Префикс имён. У расширения есть свойство «Префикс имён». Если в одной версии префикс мр_, а в другой МоеР_, все собственные объекты и обработчики будут числиться разными.

⚙️ Режим совместимости. Расширение с режимом совместимости новее, чем у основной конфигурации, не подключится. Перед сравнением кода сверьте это свойство у обеих версий и у основной конфигурации.

🎯 Назначение. Свойство «Назначение» (исправление, адаптация, дополнение) влияет на порядок применения нескольких расширений. Если два расширения перехватывают один метод, разница в назначении меняет итоговое поведение, хотя код каждого из них не менялся.

📦 Расширение, снятое из пользовательского режима. В типовых конфигурациях на БСП расширение можно сохранить в файл из списка расширений в разделе администрирования (в БП 3.0 — Администрирование → Печатные формы, отчеты и обработки → Расширения). Такой .cfe ничем не хуже выгруженного из Конфигуратора, его можно сравнивать так же.

Автоматическое сравнение конфигурации и расширения на OneScript

Когда расширений пять и больше, а обновления идут ежемесячно, ручная проверка начинает съедать день. Схема автоматизации простая:

  1. Выгрузить в XML основную конфигурацию до обновления (каталог old).
  2. Выгрузить в XML основную конфигурацию копии базы после обновления (каталог new).
  3. Выгрузить в XML каждое расширение (каталог ext).
  4. Найти в ext все заимствованные объекты и проверить, поменялись ли их файлы между old и new.

Шаги 1–3 — это команды /DumpConfigToFiles из раздела выше. Их можно вызвать из того же скрипта через ЗапуститьПриложение. Шаг 4 делает такой скрипт:

// Запуск: oscript compare_adopted.os D:\dump\ext D:\dump\old D:\dump\new
// Каталоги передавать без завершающей косой черты.

Функция ПрочитатьФайл(Путь)
	Файл = Новый Файл(Путь);
	Если НЕ Файл.Существует() Тогда
		Возврат Неопределено;
	КонецЕсли;
	Чтение = Новый ЧтениеТекста(Путь, КодировкаТекста.UTF8);
	Текст = Чтение.Прочитать();
	Чтение.Закрыть();
	Возврат Текст;
КонецФункции

Процедура ДобавитьФайлы(Каталог, Корень, Пути)
	Папка = Новый Файл(Каталог);
	Если НЕ Папка.Существует() Тогда
		Возврат;
	КонецЕсли;
	Для Каждого Ф Из НайтиФайлы(Каталог, "*", Истина) Цикл
		Если Ф.ЭтоФайл() Тогда
			Пути.Вставить(Сред(Ф.ПолноеИмя, СтрДлина(Корень) + 1), Истина);
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

КаталогРасширения = АргументыКоманднойСтроки[0];
КаталогСтарый = АргументыКоманднойСтроки[1];
КаталогНовый = АргументыКоманднойСтроки[2];
Метка = "<ObjectBelonging>Adopted</ObjectBelonging>";
Найдено = 0;

Для Каждого Ф Из НайтиФайлы(КаталогРасширения, "*.xml", Истина) Цикл
	Текст = ПрочитатьФайл(Ф.ПолноеИмя);
	Если Текст = Неопределено ИЛИ СтрНайти(Текст, Метка) = 0 Тогда
		Продолжить;
	КонецЕсли;

	// Путь объекта относительно корня выгрузки, например \Catalogs\Номенклатура.xml
	Отн = Сред(Ф.ПолноеИмя, СтрДлина(КаталогРасширения) + 1);
	Пути = Новый Соответствие;
	Пути.Вставить(Отн, Истина);

	// Подкаталог объекта: формы, модули, макеты
	ИмяПапки = Лев(Отн, СтрДлина(Отн) - 4);
	ДобавитьФайлы(КаталогСтарый + ИмяПапки, КаталогСтарый, Пути);
	ДобавитьФайлы(КаталогНовый + ИмяПапки, КаталогНовый, Пути);

	Изменено = 0;
	Для Каждого Элемент Из Пути Цикл
		Если ПрочитатьФайл(КаталогСтарый + Элемент.Ключ) <> ПрочитатьФайл(КаталогНовый + Элемент.Ключ) Тогда
			Изменено = Изменено + 1;
		КонецЕсли;
	КонецЦикла;

	Если Изменено > 0 Тогда
		Сообщить(СтрШаблон("%1: изменено файлов %2", Отн, Изменено));
		Найдено = Найдено + 1;
	КонецЕсли;
КонецЦикла;

Сообщить(СтрШаблон("Заимствованных объектов, которые тронуло обновление: %1", Найдено));

Скрипт не ищет различия построчно — он выдаёт короткий список того, что надо открыть руками. Например, из 40 заимствованных объектов обновление тронуло 6. Эти 6 вы и сравниваете в WinMerge, а остальные 34 пропускаете.

Файл Configuration.xml почти всегда попадёт в список: в нём меняется номер версии. Это нормально, его можно не смотреть.

Для хранения выгрузок в Git есть готовые инструменты сообщества на OneScript, например gitsync и библиотека v8runner для управления Конфигуратором. С ними история изменений и расширения, и основной конфигурации видна в обычном git log.

Отдельно стоит пакетная проверка применимости: команда Конфигуратора /CheckCanApplyConfigurationExtensions. Её удобно вызывать последним шагом скрипта после обновления копии базы — код возврата и файл /Out скажут, подключатся ли расширения.

Ошибки при сравнении и как их не допустить

  • ❌ Сравнивают рабочую базу вместо копии. Обновление основной конфигурации ради проверки расширений делайте только в копии. Если расширение не подключится в рабочей базе, пострадают все пользователи с этой доработкой.
  • ❌ Смотрят только на успешное подключение. Проверка применимости молчит, если вы перехватили метод через &После, а поставщик перенёс нужную логику в другую процедуру. Расширение подключится, но обработчик перестанет срабатывать. Такие случаи видны только в XML-diff модулей.
  • ❌ Сравнивают «Основную конфигурацию» вместо «Конфигурации базы данных». Если основную конфигурацию поменяли, но не обновили базу, выгрузка и проверка покажут не то, что реально работает у пользователей.
  • ❌ Путают кодировки и переводы строк. Если одну выгрузку открыли и пересохранили в редакторе, diff покажет изменения в каждой строке. В WinMerge включите игнорирование различий в окончаниях строк.
  • ❌ Забывают про несколько расширений. Если два расширения заимствуют одну форму, проверять нужно оба — и в том порядке, в каком они применяются.

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

Можно ли объединить расширение с основной конфигурацией, чтобы убрать его?
Готовой команды «влить расширение в конфигурацию» в Конфигураторе нет. Изменения переносят вручную: собственные объекты копируют, перехваты превращают в правки кода основной конфигурации. Для этого основную конфигурацию придётся включить в редактирование, а это усложнит следующие обновления.
Почему после обновления расширение подключилось, но доработка не работает?
Проверка применимости контролирует наличие заимствованных объектов и методов, контролируемые свойства и текст методов под &ИзменениеИКонтроль. Перехваты &Перед, &После и &Вместо подключатся, даже если поставщик поменял логику вокруг перехваченной процедуры. Сравните модуль объекта в выгрузках до и после обновления.
Нужен ли монопольный режим, чтобы выгрузить расширение в XML?
Нет, выгрузка в файлы только читает конфигурацию. Монопольный доступ нужен для обновления конфигурации базы данных, а не для выгрузки.
Чем сравнивать выгрузки, если на сервере нельзя ставить программы?
Скопируйте каталоги на свой компьютер или используйте git diff --no-index, если Git уже установлен. Выгрузка — обычные текстовые файлы, сравнивать их можно где угодно.
Можно ли сравнить расширения из двух разных баз?
Да. Сохраните расширение из каждой базы в .cfe или выгрузите в XML и сравните файлы. Если расширение в базах создавали независимо, сравнивайте только XML: идентификаторы объектов будут разными.