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

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

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

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

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

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

Чем клиентский контекст отличается от серверного

Клиентский контекст — это код, выполняемый на компьютере пользователя в процессе тонкого, толстого или веб-клиента. Здесь доступны интерактивные возможности: диалоги, предупреждения, работа с файлами пользователя, OLE/COM-объекты (в толстом клиенте). Но напрямую обращаться к базе данных, выполнять запросы и использовать прикладные объекты (ДокументыОбъект, СправочникиОбъект) нельзя — для этого нужен вызов сервера.

Серверный контекст выполняется в рабочем процессе сервера 1С:Предприятия (или в файловом варианте — в специальном серверном потоке клиентского приложения). Здесь доступны запросы, транзакции, объектная модель данных, менеджеры прикладных объектов. Но недоступны любые интерактивные вызовы: попытка показать сообщение через модальное окно или открыть диалог выбора файла на сервере приведёт к ошибке.

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

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

Самый надёжный способ понять, где выполнится процедура формы, — посмотреть на директиву перед её объявлением. Директива пишется в модуле формы непосредственно перед строкой Процедура или Функция:

&НаКлиенте

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

// выполняется на клиенте

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

&НаСервере

Процедура ЗаписатьДанные()

// выполняется на сервере

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

Доступные директивы:

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

Процедуры без директивы в модуле формы по умолчанию компилируются на сервере с контекстом. Это частая причина путаницы у начинающих: отсутствие директивы не означает «везде», а означает серверный контекст.

Как определить контекст по свойствам модуля

Для общих модулей контекст задаётся флажками в палитре свойств конфигуратора. Откройте свойства общего модуля (правый клик → «Свойства») и посмотрите отметки:

  • Сервер — модуль компилируется на сервере;
  • Клиент (обычное приложение) — доступен в толстом клиенте обычного приложения;
  • Клиент (управляемое приложение) — доступен в тонком и веб-клиенте;
  • Вызов сервера — разрешает обращаться к серверному модулю с клиента;
  • Привилегированный режим — код выполняется без проверки прав доступа.

Если установлены одновременно «Сервер» и «Клиент (управляемое приложение)», модуль компилируется в обоих контекстах, и внутри него нужно разделять код директивами препроцессора #Если Сервер Тогда ... #Иначе ... #КонецЕсли. Именно такие модули чаще всего требуют динамической проверки контекста.

Как проверить контекст модуля в конфигураторе
  1. 1
    Откройте общий модуль в дереве конфигурации
  2. 2
    Вызовите палитру свойств (правый клик — Свойства)
  3. 3
    Посмотрите флажки Сервер и Клиент (управляемое приложение)
  4. 4
    Если отмечены оба — ищите в коде инструкции #Если Сервер Тогда
  5. 5
    Для модуля формы смотрите директивы & перед каждой процедурой

Как программно определить клиент или сервер

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

Функция ЭтоСервер() Экспорт

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

Возврат Истина;

#Иначе

Возврат Ложь;

#КонецЕсли

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

Инструкции препроцессора #Если вычисляются на этапе компиляции модуля, поэтому это самый быстрый и надёжный способ — лишнего кода в рантайме не остаётся вообще. Доступные символы препроцессора: Сервер, ТолстыйКлиентОбычноеПриложение, ТолстыйКлиентУправляемоеПриложение, ТонкийКлиент, ВебКлиент, МобильныйКлиент.

Если препроцессор недоступен (например, код внешней обработки должен работать везде без перекомпиляции), применяют проверку через Вычислить() или анализ типа:

Функция ЭтоКлиентскоеОкружение()

Попытка

Результат = Вычислить("ПолучитьОкна()");

Возврат Истина; // клиент

Исключение

Возврат Ложь; // сервер

КонецПопытки;

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

1c
#Если Сервер Тогда
    Сообщить("Код выполняется на сервере");
#ИначеЕсли ТонкийКлиент Тогда
    Сообщить("Код выполняется в тонком клиенте");
#ИначеЕсли ВебКлиент Тогда
    Сообщить("Код выполняется в веб-клиенте");
#КонецЕсли

Как узнать режим запуска и тип клиента

Смежная задача — понять, в каком клиенте работает пользователь: тонком, толстом или веб. Для этого служит функция ТекущийРежимЗапуска(), которая возвращает значение системного перечисления:

  • РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение — управляемые формы;
  • РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение — обычные формы;
  • Неопределено — код выполняется на сервере или в фоновом задании.

Информацию о типе клиента и системе даёт объект СистемнаяИнформация и функция ИнформацияОСистеме в типовых конфигурациях (БСП). Отдельно полезен метод ПараметрыСеанса — в типовых решениях туда при запуске записывают параметры клиента, которые потом доступны на сервере без повторного вызова.

Директива &НаКлиентеКлиент

Код формы выполняется на стороне пользователя

Директива &НаСервереСервер

Код выполняется на сервере с данными формы

ТекущийРежимЗапуска() = НеопределеноСервер или фоновое задание

Клиентское приложение отсутствует

Флажки Сервер + Клиент в модулеОба контекста

Нужно разделять код через #Если Сервер Тогда

Типичные ошибки при работе с контекстом

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

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

Третья ошибка — передача несериализуемых данных между контекстами. Например, вернуть с сервера на клиент объект типа Запрос или ДокументОбъект нельзя: при вызове сервера данные сериализуются, и такие типы не переживают передачу. Передавайте структуры, массивы и примитивные типы.

Типичные ошибки
01
Вызов серверного модуля без флажка Вызов сервера — ошибка неопределённой процедуры
02
Интерактивные диалоги в серверном коде — ошибка выполнения или зависание
03
Передача Запрос или ДокументОбъект с сервера на клиент — ошибка сериализации
04
Проверка контекста через ТекущийРежимЗапуска() в фоновом задании — всегда Неопределено, логика ломается
05
Процедура формы без директивы — разработчик ждёт клиент, а выполняется на сервере

Как проверить и отладить контекст на практике

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

Практический приём самопроверки — временно вставить в сомнительное место кода строку:

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

ЗаписьЖурналаРегистрации("Контекст", , , , "Выполнение на сервере");

#Иначе

Сообщить("Выполнение на клиенте");

#КонецЕсли

После запуска сценария станет очевидно, какая ветка сработала. Не забудьте удалить отладочный код после проверки.

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

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

Откуда вызвана процедура
Норма

Директива соответствует месту вызова

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

Клиент вызывает серверную процедуру без экспорта и флажка Вызов сервера

Точка останова в серверном коде
Норма

Отладчик останавливается

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

Точка не срабатывает — сервер не в отладочном режиме

Возврат данных с сервера
Норма

Структуры, массивы, примитивы

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

Попытка вернуть Запрос, СКД, объект БД

FAQ

Как понять, что код выполняется в фоновом задании?

Фоновое задание всегда выполняется на сервере, но без сеанса интерактивного пользователя. Признак: функция ТекущийРежимЗапуска() возвращает Неопределено, а получить текущий сеанс через ПолучитьТекущийСеансИнформационнойБазы() можно и проверить его тип — у фонового задания будет соответствующее имя приложения BackgroundJob.

Почему процедура с директивой &НаСервере не видна с клиента?

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

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

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

Можно ли определить контекст без препроцессора, в одной строке?

Да, через попытку вызова клиентского метода: например, Вычислить("ПолучитьОкна()") в обёртке Попытка/Исключение. На сервере вызов выбросит исключение. Способ медленнее препроцессора и используется, когда модуль компилируется в обоих контекстах без инструкций #Если.

Почему ТекущаяДата() на клиенте и сервере даёт разные значения?

На клиенте функция возвращает время компьютера пользователя, на сервере — время сервера. Это косвенный способ понять контекст и одновременно источник ошибок: для единообразия в серверном коде используйте ТекущаяДатаСеанса(), которая учитывает часовой пояс сеанса.

Итог

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

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