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

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

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

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

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

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

Ниже разобраны практические приёмы определения клиентского и серверного контекста, ограничения каждого способа и типичные ошибки, которые приводят к падению кода при переносе между клиентом и сервером.

Зачем вообще различать клиент и сервер

В файловом варианте работы разница между клиентом и сервером часто незаметна — всё выполняется в одном процессе. Но в клиент-серверном варианте (с СУБД MS SQL, PostgreSQL, Oracle или IBM Db2) сервер 1С:Предприятия — отдельный процесс на отдельной машине. Код, обращающийся к базе данных, выполняется там, а интерфейсная логика — на рабочем месте пользователя.

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

Кроме того, серверный код выполняется под учётной записью агента сервера 1С, а не пользователя Windows. Это влияет на доступ к файлам, сетевым ресурсам и внешним компонентам — частая причина «на клиенте работает, на сервере нет».

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

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

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

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

bsl
&НаСервере
Функция ПолучитьОстаток(Номенклатура)
    Запрос = Новый Запрос("ВЫБРАТЬ Остаток ИЗ РегистрНакопления.Товары.Остатки");
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

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

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

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

bsl
#Если Сервер Тогда
    Результат = ВыполнитьЗапросКБазе(Параметры);
#ИначеЕсли ТонкийКлиент Тогда
    ПоказатьПредупреждение(, "Операция доступна только на сервере");
#КонецЕсли

Дополнительно в клиентском коде можно проверить тип клиента через функцию ТекущийРежимЗапуска() — она возвращает значение системного перечисления (тонкий, толстый клиент и т.д.). Это удобно, когда логика зависит не от «клиент/сервер», а от конкретного вида клиентского приложения.

Признаки того, что код выполняется не там

На практике чаще приходится не «определять» контекст, а диагностировать, что код попал не в тот. Есть устойчивые признаки, по которым это видно.

Ошибка «Метод объекта не обнаружен»Код вызывает серверные объекты на клиенте

Проверьте, не обращается ли клиентская процедура к Документы.Имя или Запрос напрямую

Ошибка передачи данных между клиентом и серверомПопытка вернуть мутабельный объект на клиента

Замените возврат Объекта на структуру или таблицу значений

«Файл не найден» только на сервереКод ищет файл по пути клиентской машины

Перенесите обработку файла на клиента или используйте временное хранилище

Диалоги не открываютсяИнтерактивный вызов в серверной процедуре

Вынесите вопрос пользователю в клиентскую процедуру

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

Пошаговая проверка контекста при отладке

Когда поведение кода неочевидно, контекст проще всего установить отладчиком. Порядок действий стандартный.

Порядок действий
  1. 1
    Включите отладку: в конфигураторе — Отладка → Подключение, убедитесь, что видны и клиентские, и серверные предметы отладки
  2. 2
    Для сервера убедитесь, что сервер 1С запущен в отладочном режиме (ключ -debug в строке запуска агента)
  3. 3
    Поставьте точку останова в проверяемой процедуре и выполните действие в клиентском приложении
  4. 4
    Посмотрите, в каком предмете отладки остановилось выполнение — клиент или сервер 1С
  5. 5
    Проверьте директиву компиляции процедуры и свойства общего модуля, если точка не сработала

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

Типичные ошибки и ограничения

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

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

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

Проверка результата после изменений

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

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

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

Компиляция модулей
Норма

Конфигурация проверяется без ошибок во всех режимах (тонкий, веб, сервер)

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

Ошибки «Процедура или функция не определена» в одном из режимов

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

Один вызов на логическую операцию

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

Серверные вызовы внутри цикла по строкам данных

Передаваемые данные
Норма

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

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

Передача Объектов, запросов, COM-объектов

Отладка
Норма

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

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

Серверный код не останавливается — проверьте ключ -debug

FAQ

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

Надёжнее всего использовать инструкции препроцессора: #Если Сервер Тогда ... #КонецЕсли. Они срабатывают на этапе компиляции, поэтому недоступная ветка не вызовет ошибок. Универсальной функции «ЭтоСервер()» во встроенном языке нет — такую функцию обычно пишут сами в общем модуле с нужными флажками компиляции.

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

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

Почему код работает в файловой базе и падает в клиент-серверной?

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

Можно ли вызвать клиентскую процедуру с сервера?

Нет, прямого вызова «сервер → клиент» нет: сервер не знает о состоянии конкретного клиентского сеанса. Серверная процедура возвращает результат, а клиентская процедура сама решает, что с ним делать. Для интерактива логику строят так: клиент спрашивает пользователя, затем вызывает сервер.

Как передать файл с клиента на сервер для обработки?

Используйте асинхронный метод НачатьПомещениеФайла (или НачатьПомещениеФайлаНаСервер в новых версиях платформы) — файл попадёт во временное хранилище, а серверная процедура получит его адрес и сможет прочитать содержимое через ПолучитьИзВременногоХранилища.

Где посмотреть, в каких контекстах компилируется общий модуль?

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

Итог

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

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