При переводе файловой базы обычного приложения (например, 1С:Управление торговлей 10.3) в клиент-серверный режим (SQL) разработчики нередко сталкиваются с ошибками интеграции. Ситуация часто выглядит так: ранее все пользователи работали в терминальном доступе на одном сервере, и функции COM-подключения спокойно обращались к файловым путям вида D:\Base. После перехода на клиент-серверный вариант и прямого подключения пользователей с локальных компьютеров код перестает работать, так как локальный ПК клиента не имеет прямого доступа к диску сервера.
Попытка решить проблему «в лоб» добавлением директивы &НаСервере перед функцией в общем модуле обычного приложения приводит к ошибке «Метод объекта не обнаружен». Разберем детально, почему это происходит, как устроена модель выполнения кода в обычном приложении и как грамотно перенести подключение к файловой базе на сторону сервера 1С.
Проанализируем механику работы директив компиляции в платформе 1С:Предприятие:
&НаСервере, &НаКлиенте) предназначены исключительно для модулей управляемых форм и управляемых команд. В обычных формах и в общих модулях конфигурации использовать эти директивы нельзя.&НаСервере перед объявлением метода в общем модуле, платформа не может корректно распарсить заголовок функции, в результате чего экспортный метод не попадает в пространство имен модуля, и при вызове выбрасывается исключение «Метод объекта не обнаружен».В толстом клиенте обычного приложения действует следующее правило: если у общего модуля включены одновременно флаги Клиент (обычное приложение) и Сервер, то при вызове функции с клиента она по умолчанию будет выполняться на клиенте. Чтобы принудительно перенести исполнение на сервер 1С, необходимо правильно настроить свойства модуля.
Выполним следующие действия:
БонКартыСервер).&НаСервере из текста модуля перед определением функции.При таких настройках вызов БонКартыСервер.ПолучитьПодключениеКФайловойБД() с любого клиентского компьютера гарантированно передаст управление на сервер 1С:Предприятия, где локальный диск D:\Base доступен операционной системе.
При переносе кода COM-соединения на сервер необходимо учесть критические ограничения серверного контекста:
Предупреждение() не может вызываться на сервере, так как серверные процессы 1С не имеют графического интерфейса. Вызов диалоговых окон на сервере приводит к аварийной ошибке «Интерактивные операции недопустимы». Ошибки на сервере нужно логировать в журнал регистрации или передавать на клиент через вызов исключения.x86-64), вызов Новый COMОбъект("V83.COMConnector") потребует зарегистрированной 64-битной библиотеки comcntr.dll. Если база запускается под 64-битным сервером, а коннектор 32-битный, возникнет ошибка «Класс не зарегистрирован».USR1CV8) должна иметь полные права доступа (чтение, запись, изменение) на папку с файловой базой данных на сервере.Посмотрим на исправленный и безопасный пример серверной функции подключения:
Функция ПолучитьПодключениеКФайловойБД() Экспорт
КаталогБазыДанных = ПолучитьПредопределенноеЗначение("КаталогБазыДанных");
Пользователь = ПолучитьПредопределенноеЗначение("ПользовательИБ");
Пароль = ПолучитьПредопределенноеЗначение("ПарольПользователяИБ");
СтрокаПодключения = "file='" + КаталогБазыДанных + "'; usr='" + Пользователь + "'; pwd='" + Пароль + "';";
Попытка
V83COMConnector = Новый COMОбъект("V83.COMConnector");
Возврат V83COMConnector.Connect(СтрокаПодключения);
Исключение
ТекстОшибки = "Ошибка COM-подключения к файловой базе: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Интеграция.COM", УровеньЖурналаРегистрации.Ошибка,,, ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецПопытки;
КонецФункции
Теперь в клиентском коде формы или обработки обычного приложения вызываем серверный метод в блоке обработки исключений:
Попытка
Соединение = БонКартыСервер.ПолучитьПодключениеКФайловойБД();
// Дальнейшая работа с внешним COM-соединением
Исключение
Предупреждение("Не удалось подключиться к внешней базе: " + ОписаниеОшибки());
КонецПопытки;
Если перенос логики на сервер 1С затруднен из-за ограничений разрядности COM-коннектора, рассмотрим альтернативные пути:
file='\\ServerName\BaseShare';. В этом случае подключение по-прежнему может выполняться на стороне клиента, если у пользователя клиентской машины есть сетевые права к ресурсу.