Как в 1С преобразовать строку в код и получить имя SQL-базы

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки в среде "1С:Предприятие" программисты регулярно сталкиваются с нестандартными задачами автоматизации. К ним относится динамическое исполнение алгоритмов, хранящихся в текстовом виде, а также определение технических параметров текущей информационной базы (например, её имени на сервере СУБД). Разберем по шагам, как решать эти задачи эффективно, изящно и безопасно.

Динамическое выполнение кода: операторы Выполнить() и Вычислить()

Иногда логику приложения необходимо определять «на лету» — например, если формулы расчетов или условия выгрузки хранятся в справочниках или внешних файлах. В платформе 1С для преобразования текстовой строки в исполняемый код предусмотрены два встроенных инструмента: Выполнить() и Вычислить(). Проанализируем различия между ними, так как их часто путают.

Инструмент 1. Оператор Выполнить()

Этот оператор предназначен для исполнения полноценных блоков кода. Внутри передаваемой строки могут содержаться любые конструкции встроенного языка 1С: условия Если...Тогда, циклы Для Каждого, создание новых объектов конфигурации и вызовы процедур.

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

Рассмотрим практический пример совместной работы с контекстом переменных:


// Объявляем переменную в текущем контексте
РезультатОбработки = Неопределено;

// Формируем исполняемый алгоритм в виде строки
СтрокаКода = "
Если Константы.ИспользоватьЛимиты.Получить() Тогда
    РезультатОбработки = Справочники.Лимиты.НайтиПоРеквизиту(""Активный"", Истина);
Иначе
    РезультатОбработки = Справочники.Лимиты.ПустаяСсылка();
КонецЕсли;";

// Выполняем динамический код
Выполнить(СтрокаКода);

// Переменная РезультатОбработки успешно изменила свое значение
Если ЗначениеЗаполнено(РезультатОбработки) Тогда
    // Продолжаем работу с полученным объектом
КонецЕсли;

Инструмент 2. Функция Вычислить()

В отличие от предыдущего оператора, Вычислить() — это функция. Она предназначена исключительно для расчета конкретного выражения (математического, логического, конкатенации строк или вызова другой функции) и **возвращает** результат вычисления.

Написать внутри передаваемой строки управляющую конструкцию вроде цикла или присвоить значение переменной напрямую нельзя. Посмотрим на пример вычисления простых выражений:


// Пример 1: Математическое выражение
ФормулаРасчета = "2 * (ПараметрА + ПараметрБ)";
ПараметрА = 15;
ПараметрБ = 5;

ИтоговоеЗначение = Вычислить(ФормулаРасчета); // Вернет 40

// Пример 2: Динамический вызов функции
ИмяЭкспортнойФункции = "ОбщегоНазначения.ПолучитьВремяСервера()";
ТекущееВремя = Вычислить(ИмяЭкспортнойФункции);

Безопасность при динамическом выполнении кода

Использование динамического выполнения кода на стороне сервера несет в себе колоссальные угрозы безопасности, аналогичные SQL-инъекциям. Если строка кода формируется на основе данных, которые вводит конечный пользователь (например, через текстовое поле на форме), злоумышленник может внедрить деструктивный код (например, команду удаления базы данных или несанкционированную выгрузку конфиденциальной информации).

Выясним, как обезопасить систему. Согласно стандартам разработки 1С (стандарт #std770), любой динамический код должен выполняться в безопасном режиме работы платформы. В безопасном режиме запрещены операции с файловой системой сервера, запуск внешних приложений, работа с COM-объектами и другие потенциально опасные действия.

Рассмотрим, как правильно реализовать безопасный вызов:


// Принудительно включаем безопасный режим исполнения
УстановитьБезопасныйРежим(Истина);

Попытка
    Выполнить(ПользовательскийАлгоритм);
Исключение
    // Записываем ошибку в технологический журнал
    ЗаписьЖурналаРегистрации("ДинамическийКод", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
КонецПопытки;

// Возвращаем стандартный режим работы
УстановитьБезопасныйРежим(Ложь);

Как программно узнать имя базы 1С и SQL-сервера

Второй вопрос, который часто возникает у разработчиков — как программно определить параметры подключения текущей информационной базы. Платформа предоставляет для этого стандартную функцию СтрокаСоединенияИнформационнойБазы().

Однако возвращаемое значение представляет собой необработанную техническую строку, формат которой зависит от режима работы системы:

Обычно программисты начинают парсить эту строку с помощью строковых функций Найти() и Сред(). Но существует изящный разработческий «лайфхак», основанный на работе функции НСтр().

Формат строки соединения платформы полностью совпадает со структурой строк локализации 1С. Мы можем использовать это свойство, чтобы одной строчкой кода вытащить чистое имя базы данных как для файлового, так и для серверного вариантов работы:


// Лайфхак получения имени базы данных или пути к каталогу
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
ИмяБазы = Макс(НСтр(СтрокаСоединения, "Ref"), НСтр(СтрокаСоединения, "File"));

Этот код автоматически вернет либо логическое имя базы на кластере 1С (из параметра Ref), либо путь к каталогу на диске (из параметра File).

Определение физического имени базы на SQL-сервере

Важно понимать разницу: имя базы в параметре Ref="..." — это имя информационной базы на **Кластере серверов 1С**. На самом SQL-сервере (MS SQL, PostgreSQL и др.) физическая база данных в СУБД может называться совершенно по-другому.

Если вам необходимо узнать именно **физическое имя базы в СУБД** (например, для построения прямых запросов или администрирования), обычных прав пользователя "1С:Предприятие" будет недостаточно. Потребуется выполнить подключение к агенту сервера 1С через COM-соединение:


// Создаем COM-соединитель с сервером 1С
Connector = Новый COMОбъект("V83.COMConnector");

// Подключаемся к агенту сервера (требуются права администратора)
AgentConnection = Connector.ConnectAgent("ИмяСервераКластера");

// Получаем список кластеров и выбираем рабочий
Clusters = AgentConnection.GetClusters();
РабочийCluster = ClustersValue[0]; // Выбираем нужный кластер

// Проходим аутентификацию на кластере
AgentConnection.Authenticate(РабочийCluster, "", "");

// Находим нашу информационную базу среди зарегистрированных на кластере
СписокБаз = AgentConnection.GetInfoBases(РабочийCluster);
Для Каждого БазаДанных Из СписокБаз Цикл
    Если ВРег(БазаДанных.Name) = ВРег(ИмяБазы1С) Тогда
        // Получаем точные физические параметры СУБД
        ИмяСервераСУБД = БазаДанных.dbServerName;
        ФизическоеИмяSQL = БазаДанных.dbName;
        Прервать;
    КонецЕсли;
КонецЦикла;

Используя этот подход, мы можем связать логическую структуру метаданных 1С с физической базой на сервере СУБД, что открывает широкие возможности для детального мониторинга и низкоуровневой оптимизации системы.

← На главную