Разработка и Конфигурация · 10 мин
Как в 1С определить, где выполняется код: клиент или сервер
Как в 1С определить, выполняется код на клиенте или на сервере: директивы компиляции, функции проверки, типичные ошибки и рекомендации для разработчиков.
В клиент-серверной архитектуре 1С:Предприятие один и тот же модуль может компилироваться и выполняться в разных контекстах — на тонком клиенте, веб-клиенте или на сервере приложений. От того, где именно исполняется код, зависят доступные объекты, типы данных и даже синтаксис: например, работа с файловой системой на сервере и на клиенте устроена принципиально по-разному.
Разработчику регулярно приходится отвечать на вопрос «где сейчас выполняется этот код» — при отладке общих модулей, при переносе логики между клиентом и сервером, при диагностике ошибок вида «Переменная не определена» или «Метод объекта не обнаружен». Существует несколько штатных способов определить контекст выполнения: директивы компиляции, встроенные функции проверки и анализ свойств конфигурации.
Ниже разобраны практические приёмы определения клиентского и серверного контекста, ограничения каждого способа и типичные ошибки, которые приводят к падению кода при переносе между клиентом и сервером.
Зачем вообще различать клиент и сервер
В файловом варианте работы разница между клиентом и сервером часто незаметна — всё выполняется в одном процессе. Но в клиент-серверном варианте (с СУБД MS SQL, PostgreSQL, Oracle или IBM Db2) сервер 1С:Предприятия — отдельный процесс на отдельной машине. Код, обращающийся к базе данных, выполняется там, а интерфейсная логика — на рабочем месте пользователя.
Если не разделять контексты, возникают характерные проблемы: код падает с ошибками о недоступных методах, обмен данными между клиентом и сервером становится чрезмерным (каждый вызов — сетевой обмен), а попытка передать на клиент мутабельные объекты вроде ДокументОбъект приводит к ошибке сериализации.
Кроме того, серверный код выполняется под учётной записью агента сервера 1С, а не пользователя Windows. Это влияет на доступ к файлам, сетевым ресурсам и внешним компонентам — частая причина «на клиенте работает, на сервере нет».
Директивы компиляции: &НаКлиенте и &НаСервере
Самый явный способ задать контекст — директивы компиляции в модулях форм и командах. Директива ставится перед объявлением процедуры или функции и жёстко определяет, где код будет скомпилирован и выполнен.
- &НаКлиенте — процедура выполняется на клиенте. Доступны элементы формы, работа с файлами пользователя, оповещения. Недоступны запросы к базе и серверные объекты.
- &НаСервере — процедура выполняется на сервере. Доступны запросы, менеджеры объектов, обращение к базе. Недоступны интерактивные диалоги и элементы формы напрямую.
- &НаСервереБезКонтекста — серверная процедура без передачи данных формы. Работает быстрее, но реквизиты формы нужно передавать параметрами.
- &НаКлиентеНаСервереБезКонтекста — код компилируется в обоих контекстах; использовать можно только ограниченное подмножество языка.
Проверить, какая директива назначена процедуре, можно прямо в конфигураторе — она указана в строке перед именем. Если директива не указана в модуле формы, платформа по умолчанию считает процедуру клиент-серверной, что часто вводит в заблуждение при отладке.
&НаСервере
Функция ПолучитьОстаток(Номенклатура)
Запрос = Новый Запрос("ВЫБРАТЬ Остаток ИЗ РегистрНакопления.Товары.Остатки");
Возврат Запрос.Выполнить().Выгрузить();
КонецФункцииКак определить контекст внутри общего модуля
Общие модули компилируются согласно своим свойствам: флажки «Клиент (управляемое приложение)», «Сервер», «Внешнее соединение». Если включены и клиент, и сервер, код внутри модуля должен сам решать, какая ветка ему доступна. Для этого используются инструкции препроцессора.
Инструкции #Если ... #Тогда ... #КонецЕсли обрабатываются на этапе компиляции, поэтому недоступная ветка просто не попадёт в исполняемый код и не вызовет ошибки. Основные символы препроцессора: Сервер, ТонкийКлиент, ТолстыйКлиентОбычноеПриложение, ТолстыйКлиентУправляемоеПриложение, ВебКлиент, МобильныйКлиент, ВнешнееСоединение.
#Если Сервер Тогда
Результат = ВыполнитьЗапросКБазе(Параметры);
#ИначеЕсли ТонкийКлиент Тогда
ПоказатьПредупреждение(, "Операция доступна только на сервере");
#КонецЕслиДополнительно в клиентском коде можно проверить тип клиента через функцию ТекущийРежимЗапуска() — она возвращает значение системного перечисления (тонкий, толстый клиент и т.д.). Это удобно, когда логика зависит не от «клиент/сервер», а от конкретного вида клиентского приложения.
Признаки того, что код выполняется не там
На практике чаще приходится не «определять» контекст, а диагностировать, что код попал не в тот. Есть устойчивые признаки, по которым это видно.
Проверьте, не обращается ли клиентская процедура к Документы.Имя или Запрос напрямую
Замените возврат Объекта на структуру или таблицу значений
Перенесите обработку файла на клиента или используйте временное хранилище
Вынесите вопрос пользователю в клиентскую процедуру
Отдельный сигнал — резкий рост времени выполнения при переносе базы из файлового в клиент-серверный вариант. Обычно это означает, что в цикле идут серверные вызовы с клиента: каждый вызов — отдельный сетевой обмен. Лечится переносом всей логики цикла в одну серверную процедуру.
Пошаговая проверка контекста при отладке
Когда поведение кода неочевидно, контекст проще всего установить отладчиком. Порядок действий стандартный.
- 1Включите отладку: в конфигураторе — Отладка → Подключение, убедитесь, что видны и клиентские, и серверные предметы отладки
- 2Для сервера убедитесь, что сервер 1С запущен в отладочном режиме (ключ -debug в строке запуска агента)
- 3Поставьте точку останова в проверяемой процедуре и выполните действие в клиентском приложении
- 4Посмотрите, в каком предмете отладки остановилось выполнение — клиент или сервер 1С
- 5Проверьте директиву компиляции процедуры и свойства общего модуля, если точка не сработала
Если точка останова в серверной процедуре не срабатывает, чаще всего причина одна из двух: сервер запущен без ключа отладки, либо модуль скомпилирован только на клиенте (в свойствах общего модуля снят флажок «Сервер»).
Типичные ошибки и ограничения
Ещё одно ограничение касается веб-клиента: там недоступна прямая работа с файловой системой без расширения работы с файлами, а часть методов требует асинхронного вызова. Код, написанный для тонкого клиента, не всегда переносится в веб-клиент без доработки.
Удобный приём: в серверных общих модулях, которые вызываются с клиента, возвращайте только простые типы — структуры, массивы, таблицы значений. Это исключает целый класс ошибок сериализации и упрощает отладку границы клиент-сервер.
Проверка результата после изменений
После переноса логики между контекстами стоит прогнать короткий контрольный список, чтобы убедиться, что граница клиент-сервер выстроена правильно.
Как проверить результат
Конфигурация проверяется без ошибок во всех режимах (тонкий, веб, сервер)
Ошибки «Процедура или функция не определена» в одном из режимов
Один вызов на логическую операцию
Серверные вызовы внутри цикла по строкам данных
Только сериализуемые типы: структуры, массивы, таблицы значений, ссылки
Передача Объектов, запросов, COM-объектов
Точки останова срабатывают в ожидаемом предмете отладки
Серверный код не останавливается — проверьте ключ -debug
FAQ
Как программно узнать, что код выполняется на сервере?
Надёжнее всего использовать инструкции препроцессора: #Если Сервер Тогда ... #КонецЕсли. Они срабатывают на этапе компиляции, поэтому недоступная ветка не вызовет ошибок. Универсальной функции «ЭтоСервер()» во встроенном языке нет — такую функцию обычно пишут сами в общем модуле с нужными флажками компиляции.
Чем &НаСервере отличается от &НаСервереБезКонтекста?
Процедура &НаСервере получает на сервере весь контекст формы — реквизиты, данные объекта. Это удобно, но данные формы сериализуются при каждом вызове. &НаСервереБезКонтекста передаёт форму на сервер без её данных: быстрее, но нужные значения придётся передавать параметрами явно.
Почему код работает в файловой базе и падает в клиент-серверной?
В файловом варианте клиент и «сервер» выполняются в одном процессе, поэтому размывание контекстов незаметно. В клиент-серверном варианте обращения к недоступным в контексте объектам вызывают ошибки. Проверяйте конфигурацию в режиме клиент-серверной компиляции заранее — конфигуратор умеет это делать через «Проверка конфигурации».
Можно ли вызвать клиентскую процедуру с сервера?
Нет, прямого вызова «сервер → клиент» нет: сервер не знает о состоянии конкретного клиентского сеанса. Серверная процедура возвращает результат, а клиентская процедура сама решает, что с ним делать. Для интерактива логику строят так: клиент спрашивает пользователя, затем вызывает сервер.
Как передать файл с клиента на сервер для обработки?
Используйте асинхронный метод НачатьПомещениеФайла (или НачатьПомещениеФайлаНаСервер в новых версиях платформы) — файл попадёт во временное хранилище, а серверная процедура получит его адрес и сможет прочитать содержимое через ПолучитьИзВременногоХранилища.
Где посмотреть, в каких контекстах компилируется общий модуль?
В конфигураторе откройте свойства общего модуля: флажки «Клиент (управляемое приложение)», «Клиент (обычное приложение)», «Сервер», «Внешнее соединение» определяют контексты компиляции. Если включено несколько флажков, код внутри должен учитывать различия через инструкции препроцессора.
Что важно запомнить
Контекст выполнения в 1С задаётся директивами компиляции и свойствами общих модулей, а разграничение внутри кода делается инструкциями препроцессора #Если Сервер. Главные правила: серверные вызовы не помещать в циклы, на клиент передавать только сериализуемые данные, интерактивные диалоги держать на клиенте, а результат проверять отладчиком и проверкой конфигурации во всех режимах.