Обновлятор-1с. Учимся писать скрипты на OneScript (v2)
2020-03-13T20:17:33+00:00О чём вообще идёт речь?
Речь идёт о возможности написания скриптов на языке OneScript для автоматизации операций над группой баз вот на этой вкладке обновлятора:
![](//helpme1s.ru/images/Image-2017-11-22-19-10-12.png)
Что такое OneScript?
Проект является независимой кросс-платформенной реализацией виртуальной машины, исполняющей скрипты на языке 1С:Предприятие.
Иными словами, это возможность писать программы на языке 1С без использования платформы 1С:Предприятие.
И это позволяет нам в конечном итоге брать уже готовые куски кода, написанные в конфигураторе и с минимальной адаптацией переносить их в программу на OneScript.
И пусть по словам разработчиков это не главная цель проекта, но я вижу интерес именно в том, чтобы из программы на OneScript подключаться к базе 1С через внешнее соединение и выполнять некоторый полезный код.
Вы спросите - а зачем это вообще надо? Почему бы не написать этот же код в обработке и запускать через 1с стандартным способом?
Но мы ведь говорим об автоматизации и тут есть фундаментальные проблемы:
- нет способа гарантированно запустить базу и выполнить в ней код некоторой внешней обработки (кто сталкивался с этим на практике знает, что слишком многое может пойти не так, начиная с того, что до выполнения обработки просто не дойдёт из-за какого-нибудь модального окна)
- нет простого способа генерировать такую обработку программно, а ведь это может нам понадобиться, если речь идёт о выполнении полезного кода над группой баз
- нет простого способа логировать выполнение этой обработки
Все эти проблемы решает OneScript.
Зачем писать и запускать эти скрипты именно в обновляторе?
Потому что обновлятор берёт на себя ряд непростых вещей, чтобы упростить написание таких скриптов в части взаимодействия с базами.
А именно.
Список баз для обработки
Прямо в обновляторе мы выбираем для какого количества баз нужно запустить написанный нами скрипт:
![](//helpme1s.ru/images/Image-2017-11-22-19-32-29.png)
Передача параметров базы
При выполнении скрипта обновлятор сам передаёт в него необходимые параметры с информацией о текущей базе:
![](//helpme1s.ru/images/Image-2017-11-22-19-34-13.png)
Все эти параметры мы можем использовать в своём скрипте, делая его универсальным для выполнения над любым количеством выбранных баз.
Примеры таких скриптов мы можем найти в списке шаблонов обновлятора:
![](//helpme1s.ru/images/Image-2017-11-22-19-35-28.png)
Предварительная архивация базы
При необходимости обновлятор обеспечит создание резервной копии перед выполнением скрипта:
![](//helpme1s.ru/images/Image-2017-11-22-19-36-42.png)
Эта резервная копия будет согласована с общей системой архивации, то есть её также можно подвергать "тюнингу" в дополнительных настройках обновлятора. Такая копия всегда будет иметь метку "перед опасной операцией".
Блокировка, разблокировка базы
При необходимости обновлятор выполнит полную блокировку базы перед выполнением вашего скрипта и разблокировку после:
![](//helpme1s.ru/images/Image-2017-11-22-12-05-57.png)
И это одна из ключевых "фич" обновлятора - ведь, например, корректное выполнение блокировки серверной базы в общем случае является достаточно нетривиальной задачей.
Нужно "разрулить" текущие подключения пользователей, административные подключения, выполнение фоновых задач. И всё это через общение напрямую с кластером 1с.
Сохранение отчётов
Обновлятор сохраняет историю выполнения таких скриптов в менеджере отчётов.
Как в общем виде:
![](//helpme1s.ru/images/Image-2017-11-22-19-42-15.png)
Так и в детальном:
![](//helpme1s.ru/images/Image-2017-11-22-19-42-51.png)
Уведомление на почту
Если у вас настроены уведомления на почту (все или только при ошибках)...
![](//helpme1s.ru/images/Image-2017-11-22-12-23-07.png)
... то информация о выполнении скриптов (включая детальные отчёты) будет приходить к вам точно также, как и информация о выполнении других операций из обновлятора:
![](//helpme1s.ru/images/Image-2017-11-22-12-27-32.png)
![](//helpme1s.ru/images/Image-2017-11-22-12-27-56.png)
Запуск скрипта по расписанию
Для добавления скрипта в запуск по расписанию следует сохранить сам скрипт:
![](https://helpme1s.ru/images/Image-2019-08-28-10-36-23.png)
Далее у нас есть 2 варианта:
1 (быстрый, но не очень удобный способ). При сохранении скрипта мы можем установить опцию "Настроить однократный запуск скрипта ...":
![](//helpme1s.ru/images/Image-2017-11-22-12-31-31.png)
И далее уже отредактировать расписание этого задания непосредственно в планировщике Windows.
2 (чуть более медленный, но самый удобный). После того как вы сохранили скрипт (не добавляя его в планировщик Windows) вернитесь в главное окно Обновлятора на закладку "Настройки программы".
Далее нажмите кнопку "Расписание"...
![](https://helpme1s.ru/images/Image-2019-08-28-10-39-43.png)
И создайте задачу с типом операции "Запуск скрипта":
![](https://helpme1s.ru/images/Image-2019-08-28-10-40-59.png)
Укажите ваш сохраненный скрипт по ссылке "выбрать скрипт для запуска...".
Облачный мониторинг
При сохранении скрипта нам также доступна опция для облачного мониторинга его работы - совершенно потрясающая возможность на мой взгляд. Вот здесь подробнее об облачном мониторинге.
Многопоточное выполнение скриптов
О том как запускать скрипт параллельно для нескольких баз подробно рассказывается здесь.
Что ещё полезно изучить перед написанием скриптов?
Ну, конечно же, сам язык 1С. Куда же без него... ![:)](//helpme1s.ru/wp-includes/images/smilies/icon_smile.gif)
Прежде всего есть вот этот справочник языка 1С с примерами: ссылка.
Также стоит пробежаться по отличиям OneScript от стандартного языка 1С. Их немного (ссылка).
Ну, и наконец, у OneScript есть также свой синтакс-помощник.
Изучать сторонние библиотеки на OneScript (которые также можно подключать в обновлятор) на первом этапе я не советую. Вы сможете вернуться к ним, когда освоитесь с простейшими скриптами в достаточной мере.
Ну, поехали!
Хватит говорить про скрипты - давайте их писать
Изучаем структуру простейшего скрипта
Для этого выберем из шаблонов пункт "1. Привет, база".
В редактор вставится шаблон простейшего скрипта:
Сам скрипт (раскрыть)
#use "updater1c"
// ****************************************************************************
// Переменные модуля
// ****************************************************************************
Перем errors; // Признак того, что при выполнении скрипта были ошибки.
Перем updater; // Обновлятор, через который мы получаем информацию о базе,
// а также вызываем различные функции обновлятора.
Перем connector; // Коннектор для подключения к базе.
Перем v8; // Само подключение к базе через коннектор.
// ****************************************************************************
// Ваш код для выполнения обновлятором
// ****************************************************************************
Процедура Главная()
Сообщить("Привет, " + updater.BaseName);
КонецПроцедуры
// ****************************************************************************
// Служебные процедуры
// ****************************************************************************
Процедура ПриНачалеРаботы()
errors = Ложь;
updater = Новый Updater1C;
// Если в скрипте не планируется использовать
// подключение к базе - просто закомментируйте
// две нижние строки.
connector = updater.CreateConnector();
v8 = updater.BaseConnectNew(connector);
КонецПроцедуры
Процедура ПриОкончанииРаботы()
Если v8 <> Неопределено Тогда
Попытка
ОсвободитьОбъект(v8);
v8 = Неопределено;
Исключение
КонецПопытки;
КонецЕсли;
Если connector <> Неопределено Тогда
Попытка
ОсвободитьОбъект(connector);
connector = Неопределено;
Исключение
КонецПопытки;
КонецЕсли;
Если updater <> Неопределено Тогда
Попытка
ОсвободитьОбъект(updater);
updater = Неопределено;
Исключение
КонецПопытки;
КонецЕсли;
Если errors Тогда
ЗавершитьРаботу(1);
КонецЕсли;
КонецПроцедуры
// ****************************************************************************
// Инициализация и запуск скрипта
// ****************************************************************************
ПриНачалеРаботы();
Попытка
Главная();
updater.КодПользователяВыполнился();
Исключение
errors = Истина;
Сообщить(ОписаниеОшибки());
КонецПопытки;
ПриОкончанииРаботы(); |
Результат выполнения скрипта
Не пугайтсь
Всё, что окружает процедуру "Главная" - служебный код обновлятора, его мы всегда будем вставлять из этого шаблона.
А наш собственный код мы всегда будем начинать писать в процедуре "Главная".
Но прежде всего обратите внимание на строку...
... в начале скрипта.
Этим самым мы подключаем в скрипт библиотеку обновлятора, которая генерируется "на лету" перед выполнением самого скрипта.
Эта библиотека позволяет нам создавать объект типа Updater1C:
updater = Новый Updater1C; |
А затем использовать его в скрипте для связи с обновлятором.
Объект updater ключевой в нашем скрипте - именно от него мы узнаём всю необходимую информацию о текущей базе (ведь скрипт может быть запущен сразу для группы баз).
И именно его свойства и методы вставляются в скрипт вот из этих пунктов меню:
![](//helpme1s.ru/images/Image-2017-11-22-20-32-14.png)
![](//helpme1s.ru/images/Image-2017-11-22-20-32-50.png)
Далее обратите внимание вот на эти строки:
connector = updater.CreateConnector();
v8 = updater.BaseConnectNew(connector); |
Здесь мы подключаемся к базе через COM, чтобы затем выполнять в ней некоторый полезный код (об этом ниже) через переменную v8, которая и является внешним подключением к базе.
Если нашему скрипту не требуется внешнее подключение к базе (это довольно затратная по времени процедура), то просто комментируем данные строки.
Во всём остальном скрипт полностью в нашем распоряжении. Мы можем подключать свои библиотеки, писать свои процедуры и функции.
В следующих примерах я буду писать только код процедуры "Главная", а вы зная всю структуру скрипта вставляйте его уже в правильное место.
Выводим пользователей базы
А давайте поставим перед собой более интересную задачу - вывести на экран всех пользователей базы.
В платформе 1С за это отвечает переменная глобального контекста ПользователиИнформационнойБазы.
Попробуем написать в процедуре "Главная" такой код:
СписокПользователей = ПользователиИнформационнойБазы.ПолучитьПользователей(); |
Но запустив его мы получим следующую ошибку:
![](//helpme1s.ru/images/Image-2017-11-23-12-12-37.png)
Всё правильно, переменная ПользователиИнформационнойБазы - это часть глобального контекста базы, но не нашего скрипта.
И как же нам добраться до контекста базы? А очень просто - через внешнее подключение, которое мы обсуждали выше.
После такого подключение сам контекст доступен нам через переменную уже нашего скрипта v8.
Перепишем наш код следующим образом:
СписокПользователей = v8.ПользователиИнформационнойБазы.ПолучитьПользователей(); |
Запустив его, мы увидим что всё ок.
Ну а дальше пишем код точно также, как если бы мы писали его в конфигураторе:
Сообщить("Выводим всех пользователей базы:");
Для Индекс = 0 По СписокПользователей.Количество() - 1 Цикл
Сообщить(СписокПользователей.Получить(Индекс).Имя);
КонецЦикла; |
Запускаем на выполнение и видим:
![](//helpme1s.ru/images/Image-2017-11-23-12-17-38.png)
Пишем запрос к базе
Как известно почти любую информацию из базы можно и нужно получать запросами.
Давайте напишем простейший запрос, который читает из базы поля Наименование и ИНН всех элементов справочника Контрагенты.
Прежде всего попробуем создать объект типа Запрос.
В конфигураторе мы написали бы, например:
Но если запустить такой скрипт через OneScript, то получим ошибку:
![](//helpme1s.ru/images/Image-2017-11-23-13-36-59.png)
И он прав ведь типа Запрос в OneScript просто не существует.
Поэтому создавать этот объект будем на стороне платформы 1С через всё то же внешнее подключение к базе:
Запрос = v8.NewObject("Запрос"); |
Запомните этот приём, ведь при помощи него мы можем создавать и другие объекты и других типов на стороне платформы 1с, когда нам это потребуется.
Ну а дальше для нас не будет ничего необычного:
Запрос.Текст = "Выбрать Наименование, ИНН ИЗ Справочник.Контрагенты ГДЕ ЭтоГруппа = Ложь";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + " (" + Выборка.ИНН + ")");
КонецЦикла; |
Результат выполнения скрипта будет таким:
![](//helpme1s.ru/images/Image-2017-11-23-13-41-22.png)
И давайте я сразу покажу как разбивать текст запроса на несколько строк:
Запрос.Текст = "
| Выбрать Наименование, ИНН
| ИЗ Справочник.Контрагенты
| ГДЕ ЭтоГруппа = Ложь"; |
Подключение библиотек
Описание библиотек в Onescript здесь.
Сами библиотеки можно найти здесь, либо в папке lib установленного Onescript.
Так как обновлятор (с недавних пор) содержит Onescript в своём дистрибутиве, то копировать библиотеки нужно в папку обновлятора "Tools/OnescriptRunner/lib"
И уже далее в начале кода скрипта делать подключение библиотеки, например:
Обратите внимание, что мы указываем имя библиотеки без кавычек. При этом библиотека самого обновлятора подключается с кавычками:
Это потому, что библиотека обновлятора генерируется программно и располагается в папке самого скрипта.
Замечание про COM-объекты
Обязательно ознакомьтесь со статьей об использовании COM-объектов в OneScript, вот она: helpme1s.ru/ispolzovanie-com-obektov-v-onescript
Как мне придумывать свои скрипты?
Для вдохновления вначале советую разобрать и понять скрипты из шаблонов обновлятора. Это уже многое вам даст.
А если же вам нужна идея для написания скрипта, который будет полезен сотням других пользоватей, то я прошу вас - напишите об этом мне любым удобным для вас способом (ссылка). Идей у меня огромное количество, но времени и возможностей не хватает.
Я написал классный скрипт и хочу поделиться
Для этого я завёл специальный проект на github, где собираю полезные скрипты от пользователей обновлятора, чтобы как можно большее количество людей смогло использовать их в своей работе.
Хотите прислать мне свой скрипт? Прошу вас сюда (ссылка).
![](//helpme1s.ru/wp-content/uploads/2017/11/3111.jpg)
).
расскажите (кнопки поделиться ниже) о нём своим друзьям и коллегам. Сделайте это один раз и вы внесете существенный вклад в развитие сайта. На сайте
, но чем больше людей им пользуются, тем больше сил у меня для его поддержки.