1. Как все начиналось.
Обычно обновление конфигураций 1С мы делаем не по мере их выхода, а когда очень стало нужно (вышла новая отчетность, появился нужный нам функционал и т.д.). В этом случае нужно выбрать и установить несколько промежуточных обновлений, которые устанавливаются по одному за раз. Если мы планируем автоматическую установку ночью, когда никто не работает, то на это может уйти несколько дней. Это и нам, и пользователям неудобно, потому что проверки нужно делать после каждого этапа.
Наступил тот момент, когда мне пришлось заниматься обновлением типовых конфигураций. Т.к. я человек ленивый, поэтому хочется сразу сделать хорошо, чтобы потом не переделывать.
2. Начало исследования и первые сюрпризы.
Решено запланировать обновление стандартными средствами конфигурации и взять сформированные скрипты за основу.
Содержимое файла main.js с самого начала принесло сюрприз, и натолкнуло на мысль, что все будет проще, чем казалось.
// Параметры процедуры обновления
var now = new Date()
var outFileName = 'log' + now.valueOf() + '.txt' // Путь к log-файлу
var cfgFileNames = ['ПолноеИмяФайлаОбновления.cfu'] // Пути к .cf/.cfu-файлам с обновлениями
var fixFileNames = [] // Пути к .cfe файлам с исправлениями
var removeFixNames = [''] // Имена исправлений, которые необходимо удалить
Обращаем внимание, что переменная cfgFileNames, содержащая полное имя файла обновления, имеет тип массив и в комментарии "Пути" во множественном числе!? Дополнительно вспоминаем, что при установке скрипт всегда пишет "1/1". Т.е. первый из одного. Дальше по тексту модуля находим, что эта переменная обрабатывается именно как массив, и снова упоминание на "Количество файлов обновления".
log(format('Количество файлов обновления: {0}', cfgFileNames.length))
for (var i = 0; i < cfgFileNames.length; i++) {
var fileInfo = GetRequired(cfgFileNames[i], null)
var required = fileInfo.requiredVersion ? '(Обязательная)' : '';
log(format('{0}. {1} {2}', i + 1, fileInfo.filePath, required))
}
После каждого обновления нужно выполнить обработчики обновления и дождаться их завершения. Этот код тоже присутствует в файле update.js.
if (fileProperties.requiredVersion || (cfgFileIndex + 1 === cfgFileNames.length)) {
setProgress(format('Выполнение обработчиков обновления ({0}/{1})', cfgFileIndex + 1, cfgFileNames.length))
ret = executeUpdate(cfgFileIndex + 1 === cfgFileNames.length)
checkResult(ret)
}
Из него мы понимаем, что для выполнения обработчиков нужны два условия: файл не должен быть последним в пакете обновления и некий флажок "requiredVersion". Не буду загромождать кодом дальше, кто захочет посмотреть, легко найдет. Просто скажу, что за этот флажок отвечает наличие символа "+" перед именем файла. Теперь становится ясно, что просто заменив одно имя файла обновления на перечисленные через запятую и с добавленным символом "+", мы сможем за один раз установить несколько обновлений. Вот так.
var cfgFileNames = ['+ПолноеИмяФайлаОбновления1.cfu,+ПолноеИмяФайлаОбновления2.cfu,+ПолноеИмяФайлаОбновления3.cfu'] // Пути к .cf/.cfu-файлам с обновлениями
3. А что же в самой 1С?
Находим описание функции "ОбновлениеКонфигурацииКлиент.УстановитьОбновление" и смотрим описание параметров.
// Проверяет возможность установки обновления. Если возможно, то запускает
// скрипт обновления или планирует обновление на указанное время.
//
// Параметры:
// Форма - ФормаКлиентскогоПриложения - форма, из которой устанавливается обновление и которая должна быть закрыта в конце.
// Параметры - Структура - параметры установки обновления:
// * РежимОбновления - Число - вариант установки обновления. Принимаемые значения:
// 0 - сейчас, 1 - при завершении работы, 2 - планирование обновления.
// * ДатаВремяОбновления - Дата - дата планируемого обновления.
// * ВыслатьОтчетНаПочту - Булево - признак необходимости отправки отчета на почту.
// * АдресЭлектроннойПочты - Строка - адрес электронной почты для отправки отчета о результате обновления.
// * КодЗадачиПланировщика - Число - код задачи запланированного обновления.
// * ИмяФайлаОбновления - Строка - имя файла устанавливаемого обновления.
// * СоздаватьРезервнуюКопию - Число - признак необходимости создания резервной копии.
// * ИмяКаталогаРезервнойКопииИБ - Строка - каталог сохранения резервной копии.
// * ВосстанавливатьИнформационнуюБазу - Булево - признак необходимости восстановления базы.
// * ЗавершениеРаботыСистемы - Булево - признак того, что установка обновления происходит при завершении работы.
// * ФайлыОбновления - Массив - содержит значения типа Структура.
// * Исправления - Структура:
// ** Установить - Массив - пути к файлам исправлений во временном хранилище,
// которые требуется установить.
// ** Удалить - Массив - уникальные идентификаторы (Строка) исправлений, которые требуется удалить.
// * КаталогПлатформы - Строка - путь к платформе, на которой должно быть запущено обновление, если не указано
// запускается на платформе текущего сеанса.
// ПараметрыАдминистрирования - см. СтандартныеПодсистемыСервер.ПараметрыАдминистрирования.
//
Процедура УстановитьОбновление(Форма, Параметры, ПараметрыАдминистрирования) Экспорт
И это приносит первое разочарование: параметр "ИмяФайлаОбновления" имеет тип строка. Но тут же есть описание параметра "ФайлыОбновления" имеющего тип массив. Дальнейшее исследование приводит в функцию "ОбновлениеКонфигурацииКлиент.ИменаФайловОбновления" из кода которой становится понятно как это использовать.
Если ПустаяСтрока(Параметры.ИмяФайлаОбновления) Тогда
ИменаФайлов = Новый Массив;
Для Каждого ФайлОбновления Из Параметры.ФайлыОбновления Цикл
ПрефиксФайлаОбновления = ?(ФайлОбновления.ВыполнитьОбработчикиОбновления, "+", "");
ИменаФайлов.Добавить(Форматировать(ПрефиксФайлаОбновления + ФайлОбновления.ПолноеИмяФайлаОбновления));
КонецЦикла;
ИменаФайловОбновления = СтрСоединить(ИменаФайлов, ",");
Иначе
ИменаФайловОбновления = Форматировать(Параметры.ИмяФайлаОбновления);
КонецЕсли;
Нам нужно передать пустой параметр "ИмяФайлаОбновления", и в параметре "ФайлыОбновления" передать массив структур с заполненными именами файлов обновления.
Новый Структура("ВыполнитьОбработчикиОбновления, ИмяФайлаОбновления", Истина);
4. Итого.
В какой версии БСП это появилось, исследовать времени не было. На версии Бухгалтерии 116 не было описания параметра "ФайлыОбновления", но сам механизм уже присутствует. В приложенном расширении в стандартную форму установки обновлений добавлена возможность выбора списка файлов обновлений. При добавлении не проверяется возможность применимости обновлений в выбранном порядке, порядок в списке должен соответствовать порядку установки.
Расширение создано на основе конфигурации Бухгалтерия 3.0 и будет работать сразу. Обновление проводилось с версии Бух 3.0.116.27. Версия БСП в ней 3.1.6.227.
Доработок немного, и можно адаптировать под любую конфигурацию.