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

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

При разработке конфигураций на платформе 1С:Предприятие 8 часто возникает необходимость выполнить определенные действия при старте системы. Это может быть проверка заполнения ключевых констант, контроль прав текущего пользователя или актуализация настроек. Начинающие разработчики часто пытаются решить эту задачу напрямую в модуле управляемого приложения, добавляя к предопределенной процедуре ПриНачалеРаботыСистемы директиву компиляции &НаСервере. Однако в результате они сталкиваются с тем, что код не выполняется, сообщения не выводятся, а точка останова в конфигураторе загадочным образом исчезает при запуске отладки.

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

Выясняем причину: почему директива &НаСервере не работает в модуле управляемого приложения?

Для того чтобы понять суть проблемы, нам необходимо рассмотреть контекст выполнения различных модулей в 1С. Платформа строго разделяет области видимости и выполнения кода.

Модуль управляемого приложения (как и модуль обычного приложения) предназначен для описания действий, которые происходят непосредственно на стороне клиента. Он всегда компилируется и выполняется исключительно на клиенте.

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

Когда мы принудительно устанавливаем директиву &НаСервере перед процедурой ПриНачалеРаботыСистемы, происходят следующие процессы:

  1. Платформа 1С ожидает, что обработчик системного события ПриНачалеРаботыСистемы будет классическим клиентским методом.
  2. Встречая директиву &НаСервере в чисто клиентском модуле, компилятор платформы не может корректно связать эту процедуру с предопределенным событием запуска.
  3. Процедура фактически исключается из исполняемого клиентского контекста. При запуске предприятия платформа просто не находит корректного обработчика и пропускает его выполнение без вывода каких-либо предупреждений или ошибок в режиме пользователя.

Почему исчезает точка останова в конфигураторе?

Проанализируем ситуацию с точки зрения работы механизма отладки 1С. Точки останова в конфигураторе жестко привязаны к реально компилируемому и исполняемому коду.

Когда мы запускаем сеанс отладки, конфигуратор передает отладочную информацию в рабочую сессию предприятия. Происходит сверка доступных модулей и инструкций. Поскольку процедура ПриНачалеРаботыСистемы() с директивой &НаСервере не может быть скомпилирована в контексте клиента (а серверного контекста у модуля управляемого приложения физически нет), данный участок кода признается платформой "неисполняемым".

Отладчик понимает, что управление никогда не передастся на эту строку кода, и автоматически деактивирует (снимает) точку останова, чтобы не вводить разработчика в заблуждение.

Файловый режим работы и иллюзия общего контекста

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

Даже в файловом варианте платформа 1С строго эмулирует клиент-серверную архитектуру. Правила разделения контекста остаются незыблемыми:

Разберем по шагам: как правильно реализовать проверку данных при запуске?

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

Рассмотрим подробнее алгоритм правильной реализации этой задачи:

Шаг 1. Создание серверного общего модуля

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

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

Шаг 2. Написание серверной процедуры

В созданном общем модуле напишем процедуру, которая будет выполнять непосредственную работу с объектами базы данных. Обратите внимание, что процедура обязательно должна содержать ключевое слово Экспорт:


Процедура ВыполнитьПроверкуДанныхНаСервере() Экспорт
    
    // Здесь нам доступен полноценный серверный контекст
    // Мы можем выполнять запросы и работать с объектной техникой
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Пользователи.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.Пользователи КАК Пользователи";
    
    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        ВызватьИсключение "В системе нет зарегистрированных пользователей!";
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Вызов серверного метода из модуля управляемого приложения

Теперь откроем Модуль управляемого приложения. Опишем предопределенную процедуру ПриНачалеРаботыСистемы. Обратите внимание: никаких директив компиляции перед процедурой писать не нужно. Внутри нее мы просто вызываем наш метод из общего модуля:


Процедура ПриНачалеРаботыСистемы()
    
    // Вызываем серверный метод общего модуля
    ПроверкиПриЗапускеСервер.ВыполнитьПроверкуДанныхНаСервере();
    
КонецПроцедуры

При таком подходе точка останова, установленная внутри процедуры ВыполнитьПроверкуДанныхНаСервере в общем модуле, будет корректно срабатывать, так как этот код будет вызван легитимно в серверном контексте во время выполнения клиентского события.

Важный нюанс: выбор между ПриНачалеРаботыСистемы и ПередНачаломРаботыСистемы

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

Для решения этой задачи предопределенная процедура ПриНачалеРаботыСистемы не подходит по следующим причинам:

Если вам необходимо иметь возможность отменить запуск программы на основании результатов серверной проверки, используйте предопределенное событие ПередНачаломРаботыСистемы. Оно вызывается до открытия интерфейса приложения и принимает параметр Отказ.

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

В общем модуле ПроверкиПриЗапускеСервер создаем функцию, возвращающую булево значение:


Функция ПроверитьВозможностьВхода() Экспорт
    
    // Проводим необходимые проверки баз данных
    Если ПараметрыСеанса.ТекущийПользователь.Неактивен Тогда
        Возврат Ложь;
    КонецЕсли;
    
    Возврат Истина;
    
КонецФункции

В Модуле управляемого приложения обрабатываем это событие следующим образом:


Процедура ПередНачаломРаботыСистемы(Отказ)
    
    // Проверяем возможность входа на сервере
    Доступ Разрешен = ПроверкиПриЗапускеСервер.ПроверитьВозможностьВхода();
    
    Если Не ДоступРазрешен Тогда
        ПоказатьПредупреждение(, "Доступ в систему заблокирован администратором!");
        Отказ = Истина; // Прерываем запуск приложения
    КонецЕсли;
    
КонецПроцедуры

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

← На главную