К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как выполнить код на сервере

Как выполнить код на сервере в 1С: директивы &НаСервере, серверные вызовы, тонкий клиент, фоновые задания. Примеры кода, ошибки и проверка результата.

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

Механизм переноса выполнения на сервер строится на директивах компиляции (&НаСервере, &НаКлиенте, &НаСервереБезКонтекста) и на специальных приёмах: серверных вызовах из клиентского кода, фоновых заданиях и планах обмена. Ниже разобраны все основные способы с примерами кода, ограничениями и типичными ошибками.

Почему код нужно выполнять именно на сервере

На сервере доступны все ресурсы, которых нет у клиента: прямой доступ к базе данных, файловая система сервера, COM-объекты и внешние компоненты, установленные на сервере. Любая работа с объектами базы — документами, справочниками, регистрами — в тонком клиенте возможна только на сервере, потому что у тонкого клиента нет прямого подключения к СУБД.

Второй аргумент — производительность. Если из клиентского кода в цикле вызывать серверные процедуры, каждый вызов порождает сетевой обмен между клиентом и сервером. Сотня таких вызовов превращается в заметную паузу. Правильный подход — передать на сервер все необходимые данные одним вызовом, выполнить там всю логику и вернуть результат.

Третий аргумент — безопасность. Проверки прав, расчёт цен, проведение документов должны выполняться на сервере, где пользователь не может подменить логику отладчиком или модифицированным клиентом. Клиентский код считается недоверенным.

Директивы компиляции: &НаСервере, &НаКлиенте и другие

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

  • &НаКлиенте — процедура выполняется на клиенте. Доступны элементы формы, диалоги, оповещения. Недоступны запросы и объекты базы данных.
  • &НаСервере — процедура выполняется на сервере с доступом к данным формы. Можно читать реквизиты формы и объекты базы.
  • &НаСервереБезКонтекста — серверная процедура без передачи данных формы. Работает быстрее, но реквизиты формы нужно передавать параметрами.
  • &НаКлиентеНаСервереБезКонтекста — код компилируется в обоих контекстах; подходит для вспомогательных функций без обращения к базе и форме.

Пример простого серверного вызова из формы:

&НаКлиенте

Процедура РассчитатьСумму(Команда)

Сумма = ПолучитьСуммуНаСервере(Объект.Ссылка);

Элементы.ИтогСумма.Заголовок = Строка(Сумма);

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьСуммуНаСервере(ДокументСсылка)

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ СУММА(Товары.Сумма) КАК Сумма

|ИЗ Документ.Реализация.Товары КАК Товары

|ГДЕ Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Выборка = Запрос.Выполнить().Выбрать();

Возврат ?(Выборка.Следующий(), Выборка.Сумма, 0);

КонецФункции

Обратите внимание: клиентская процедура просто вызывает серверную функцию по имени — платформа сама организует передачу параметра ДокументСсылка на сервер и возврат значения. Никаких дополнительных команд для «перехода на сервер» не требуется.

Серверные общие модули для кода вне форм

Если серверная логика нужна не только в одной форме, её выносят в общий модуль. Чтобы модуль компилировался и выполнялся на сервере, в его свойствах устанавливаются флаги: Сервер — обязательно, Вызов сервера — если модуль должен быть доступен из клиентского кода, Привилегированный режим — если код должен выполняться без проверки прав доступа.

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

// Общий модуль РасчетыСервер (Сервер = Истина, Вызов сервера = Истина)

Функция ПолучитьОстаток(Номенклатура, Склад) Экспорт

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ Остатки.КоличествоОстаток КАК Остаток

|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура = &Ном

| И Склад = &Склад) КАК Остатки";

Запрос.УстановитьПараметр("Ном", Номенклатура);

Запрос.УстановитьПараметр("Склад", Склад);

Выборка = Запрос.Выполнить().Выбрать();

Возврат ?(Выборка.Следующий(), Выборка.Остаток, 0);

КонецФункции

Вызов из клиентского кода выглядит так же просто: Остаток = РасчетыСервер.ПолучитьОстаток(Товар, Склад);. Платформа выполнит серверный вызов автоматически, поскольку модуль помечен как серверный с разрешённым вызовом.

Фоновые задания для длительных операций

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

Фоновое задание всегда выполняется на сервере. Запуск из кода:

// Общий модуль ДлительныеОперацииСервер (Сервер)

Процедура ОбработатьДанные(Параметры, АдресРезультата) Экспорт

Результат = Новый Структура("Обработано", 0);

Для Каждого Строка Из Параметры.Данные Цикл

// ... обработка ...

Результат.Обработано = Результат.Обработано + 1;

КонецЦикла;

ПоместитьВоВременноеХранилище(Результат, АдресРезультата);

КонецПроцедуры

// Вызов из формы

ПараметрыВыполнения = Новый Массив;

ПараметрыВыполнения.Добавить(Новый Структура("Данные", МоиДанные));

ПараметрыВыполнения.Добавить(АдресРезультата);

ФоновыеЗадания.Выполнить("ДлительныеОперацииСервер.ОбработатьДанные",

ПараметрыВыполнения, , "Обработка данных");

В типовых конфигурациях на БСП вместо прямого вызова ФоновыеЗадания.Выполнить используется подсистема «Длительные операции» (ДлительныеОперации.ВыполнитьВФоне), которая сама управляет ожиданием, оповещением формы и отображением прогресса. Если конфигурация построена на БСП — предпочтительнее именно этот механизм.

Контекст формы: когда использовать &НаСервереБезКонтекста

Разница между &НаСервере и &НаСервереБезКонтекста — в передаче данных формы. Процедура с контекстом получает на сервер весь объект формы: реквизиты, табличные части, параметры. Это удобно, но при больших табличных частях каждый вызов пересылает заметный объём данных туда и обратно.

Вариант «без контекста» передаёт только явно указанные параметры, поэтому работает быстрее и предпочтительнее, когда из формы нужны лишь несколько значений — например, ссылка и пара отборов. Правило выбора простое: если процедуре нужно читать или менять реквизиты формы напрямую — используйте &НаСервере, если достаточно передать значения параметрами — &НаСервереБезКонтекста.

Сравнение вариантов

&НаСервере

Когда нужен доступ к реквизитам и табличным частям формы. Минус — передача всего контекста формы при каждом вызове.

&НаСервереБезКонтекста

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

Общий модуль с вызовом сервера

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

Фоновое задание

Для операций дольше нескольких секунд. Не блокирует интерфейс, но результат приходит асинхронно.

Типичные ошибки и как их избежать

Самая частая проблема — обращение к недоступному контексту: попытка выполнить запрос в процедуре &НаКлиенте или обратиться к элементу формы в &НаСервереБезКонтекста. Платформа сообщит об этом либо при проверке модуля, либо в момент выполнения. Лечится переносом кода в правильный контекст: запросы — на сервер, работа с интерфейсом — на клиент.

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

Типичные ошибки
01
Серверный вызов внутри цикла на клиенте — сотни сетевых обращений и зависание интерфейса; перенесите весь цикл в одну серверную процедуру.
02
Нет флага «Вызов сервера» у общего модуля — ошибка «процедура не определена» при обращении с клиента.
03
Передача объекта Запрос или СКД параметром на сервер — такие объекты не сериализуются; создавайте их уже на сервере.
04
Запись данных из клиентских параметров в привилегированном режиме без проверок — дыра в безопасности.
05
Ожидание мгновенного результата от фонового задания — оно асинхронно, результат нужно забирать из временного хранилища по оповещению.

Как проверить, что код действительно выполнился на сервере

Самый надёжный способ — отладка. В конфигураторе включите «Отладка → Подключение» и убедитесь, что подключены и клиентский, и серверный процессы (для сервера нужен флаг «Отладка» в свойствах информационной базы или запуск сервера 1С с ключом -debug). Точка останова в серверной процедуре сработает только при подключённом серверном отладчике.

Дополнительно можно программно определить контекст выполнения:

Информация = Новый СистемнаяИнформация;

Сообщить("Тип приложения: " + Информация.ТипПлатформы);

#Если Сервер Тогда

Сообщить("Код выполняется на сервере");

#КонецЕсли

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

Контрольные точки

Как проверить результат

Точка останова в серверной процедуре
Норма

Отладчик останавливается в серверном процессе

Тревожный признак

Точка не срабатывает — серверная отладка не подключена или код ушёл на клиент

Количество серверных вызовов в замере производительности
Норма

Один-два вызова на операцию

Тревожный признак

Десятки вызовов — логика дробится, нужно объединять

Поведение формы при длительной операции
Норма

Интерфейс отзывчив, операция в фоне

Тревожный признак

Форма зависает — код выполняется синхронно в вызове

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

Можно ли выполнить код на сервере в файловом режиме работы 1С?

Да, но с оговоркой: в файловом режиме «сервер» эмулируется внутри того же процесса клиентского приложения. Директивы &НаСервере и серверные общие модули работают, код компилируется раздельно, однако физического выделенного сервера нет. Это удобно для совместимости кода, который позже будет работать в клиент-серверном варианте.

Чем &НаСервереБезКонтекста лучше &НаСервере?

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

Почему из клиентского кода не виден мой общий модуль?

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

Как передать таблицу значений с клиента на сервер?

Напрямую таблицу значений передать нельзя — она не сериализуется. Стандартный приём: преобразовать её в массив структур на клиенте, передать массив, а на сервере при необходимости выгрузить обратно в таблицу значений. Для данных табличной части формы проще использовать процедуру &НаСервере с контекстом.

Когда нужен привилегированный режим на сервере?

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

Итог

Что важно запомнить

Код на сервере 1С выполняется через директивы &НаСервере / &НаСервереБезКонтекста в формах и через серверные общие модули с флагом «Вызов сервера» вне их. Минимизируйте количество серверных вызовов, передавайте только сериализуемые данные, длительные операции выносите в фоновые задания, а привилегированный режим применяйте точечно и с проверками входных данных.