Разработчики на платформе 1С:Предприятие 8.3 часто сталкиваются с ситуацией, когда код, заключенный в инструкции препроцессора для толстого клиента, внезапно перестает работать или отрабатывает нестабильно. Особенно остро эта проблема проявляется при попытке вызвать КонструкторСхемыКомпоновкиДанных, который принципиально доступен только в режиме толстого клиента. В этой статье мы подробно разберем, почему «лыжи не едут», проанализируем причины сбоев препроцессора и найдем надежные способы решения проблемы.
Рассмотрим классическую ситуацию: программист пишет код для открытия конструктора СКД в управляемом приложении. Поскольку этот объект недоступен в тонком клиенте, код оборачивается в условие #Если ТолстыйКлиентУправляемоеПриложение Тогда. Однако при запуске приложения именно в режиме толстого клиента (через конфигуратор или параметры запуска) система внезапно переходит в ветку #Иначе, выдавая предупреждение о том, что клиент якобы не тот. Ситуация осложняется тем, что ошибка может возникать эпизодически: один раз конструктор открывается, а в девяти других случаях — нет.
Проанализируем типичный пример кода, который вызывает затруднения:
&НаКлиенте
Процедура ОткрытьСКД(Команда)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
СтандартнаяОбработка = Ложь;
Конструктор = Новый КонструкторСхемыКомпоновкиДанных;
// Логика установки схемы и редактирования
Конструктор.Редактировать(ЭтаФорма);
#Иначе
ПоказатьПредупреждение(, "Необходимо запустить толстый клиент!");
#КонецЕсли
КонецПроцедуры
Как показывает практика и подтверждают участники обсуждения, наиболее частой причиной «невидимости» контекста является локальный кэш конфигурации. Платформа 1С сохраняет скомпилированные образы модулей (так называемые .pcl файлы) для ускорения работы. Если при первом запуске (или после динамического обновления) модуль был скомпилирован для тонкого клиента, информация об этом может «залипнуть» в кэше.
Разберем по шагам, как правильно выполнить очистку, если препроцессор ведет себя неадекватно:
%AppData%\1C\1Cv8 и %LocalAppData%\1C\1Cv8, найти папки с длинными буквенно-цифровыми именами (GUID баз) и удалить их содержимое./ClearCache в строку запуска, хотя он очищает не все виды временных данных, помогая лишь частично.Важно: Очистка кэша помогает в 90% случаев, когда код написан верно, но «баг» воспроизводится хаотично.
Существует гипотеза, подтвержденная некоторыми релизами платформы (например, 8.3.22), что парсер препроцессора чувствителен к оформлению строк. Если перед символом # стоит знак табуляции или пробел, платформа в некоторых случаях может проигнорировать инструкцию или интерпретировать её неверно.
Рассмотрим правильное оформление:
Неправильно:
#Если ТолстыйКлиентУправляемоеПриложение Тогда // Здесь перед решеткой стоит Tab
Правильно:
#Если ТолстыйКлиентУправляемоеПриложение Тогда // Решетка — первый символ в строке
Хотя многие считают это «вздором», в условиях неочевидных багов платформы рекомендуется прижимать все директивы препроцессора (начинающиеся с #) к левому краю модуля без отступов.
Если проблема сохраняется, проанализируем ситуацию методом «от обратного». Вместо использования простого #Если...#Иначе, развернем полную диагностическую конструкцию. Это позволит точно понять, кем платформа «видит» текущего клиента в момент исполнения кода.
Выполним следующий диагностический запуск:
&НаКлиенте
Процедура ПроверитьКонтекст()
#Если Сервер Тогда
Сообщить("Это Сервер");
#ИначеЕсли ВебКлиент Тогда
Сообщить("Это ВебКлиент");
#ИначеЕсли ТонкийКлиент Тогда
Сообщить("Это ТонкийКлиент");
#ИначеЕсли ТолстыйКлиентОбычноеПриложение Тогда
Сообщить("Это ТолстыйКлиентОбычноеПриложение");
#ИначеЕсли ТолстыйКлиентУправляемоеПриложение Тогда
Сообщить("Это ТолстыйКлиентУправляемоеПриложение");
#Иначе
Сообщить("Контекст не определен!");
#КонецЕсли
КонецПроцедуры
Если при запуске в режиме толстого клиента вы видите сообщение «Это ТонкийКлиент», значит проблема либо в способе запуска, либо в кэше. Если же вы видите «Контекст не определен», стоит проверить целостность установки платформы.
Выясним еще одну важную деталь. Так называемое «демоническое» (динамическое) обновление часто приводит к тому, что клиентская сессия работает на старой версии скомпилированного кода, в то время как сервер уже ожидает новую. Инструкции препроцессора отрабатывают в момент компиляции модуля. Если вы изменили код или способ запуска, но не перезапустили клиента полностью после обновления конфигурации базы данных, результат работы директивы #Если может быть непредсказуемым.
Посмотрим на пример из конфигурации «Документооборот» или «Управление торговлей». Там разработчики 1С используют комбинированные проверки, чтобы минимизировать риск ошибки. Рассмотрим этот подход:
&НаКлиенте
Процедура РедактироватьСхему(Команда)
// Проверяем оба варианта толстого клиента для надежности
#Если ТолстыйКлиентОбычноеПриложение ИЛИ ТолстыйКлиентУправляемоеПриложение Тогда
Схема = ПолучитьСхемуИзХранилища();
Конструктор = Новый КонструкторСхемыКомпоновкиДанных(Схема);
Конструктор.Редактировать(ЭтотОбъект);
#Иначе
ТекстСообщения = НСтр("ru='Редактирование доступно только в толстом клиенте'");
ПоказатьПредупреждение(, ТекстСообщения);
#КонецЕсли
КонецПроцедуры
Обратите внимание: Использование ИЛИ между двумя типами толстого клиента позволяет коду быть более универсальным. Также важно помнить, что КонструкторСхемыКомпоновкиДанных требует наличия установленной схемы, иначе вызов метода Редактировать() может не произойти или вызвать исключение, которое ошибочно принимается за неверную работу препроцессора.
Проанализировав проблему, мы можем составить итоговый чек-лист для исправления ситуации, когда «лыжи не едут»:
# в директивах.Использование КонструкторСхемыКомпоновкиДанных — мощный инструмент для опытных пользователей и администраторов, и теперь вы знаете, как обеспечить его стабильную работу, обходя технические нюансы платформы 1С.