Работа с механизмом COM-соединения в 1С:Предприятие 8.3 часто преподносит сюрпризы, особенно при переходе с файловой базы на клиент-серверный вариант. Типичная ситуация: один и тот же код успешно создает и проводит документы в файловой базе, но выдает ошибку «Нарушение прав доступа» или «Произошла исключительная ситуация» при работе с MS SQL Server. Рассмотрим подробнее, почему это происходит и как решить данную проблему, проанализировав опыт разработчиков.
В файловом режиме все операции выполняются в рамках одного процесса на компьютере пользователя. В серверном режиме COM-соединение инициирует сеанс на сервере приложений 1С. Основная причина большинства проблем заключается в том, что права «Полные права» в интерфейсе не всегда автоматически означают наличие прав на низкоуровневые объекты базы данных в контексте внешнего соединения. Кроме того, серверный контекст накладывает жесткие ограничения на использование интерактивных функций и передачу объектов между модулями.
Как показывает практика, ошибка «Нарушение прав доступа» при вызове метода Записать(РежимЗаписиДокумента.Проведение) часто связана не с самим документом, а с попыткой записи в последовательности или вспомогательные регистры. Выясним причину: при проведении документа типовые конфигурации (например, УТ 11) обновляют состояние последовательностей (например, «Партии товаров организаций» или «Проведение по расчетам с поставщиками»).
Если у пользователя, под которым устанавливается COM-соединение, нет явных прав на Изменение конкретной последовательности, система выдаст ошибку прав доступа, даже если роль «Полные права» назначена. Проанализируем ситуацию: в обычном интерактивном сеансе некоторые проверки могут обходиться за счет привилегированного кода модулей, но во внешнем соединении этот механизм может работать иначе.
Что нужно сделать:
Пример кода для программной очистки последовательности (используется внутри COM-контекста):
НаборЗаписейРегистрации = COMCоединение.Последовательности.ПроведениеПоРасчетамСПоставщиками.СоздатьНаборЗаписей();
НаборЗаписейРегистрации.Отбор.Регистратор.Установить(ДокументСсылкаCOM);
НаборЗаписейРегистрации.Записать();
Одной из самых неочевидных причин отказа в записи документа через COM являются подписки на события. Рассмотрим ситуацию: при записи документа срабатывает подписка ПередЗаписью или ПриЗаписи. Если обработчик этой подписки расположен в общем модуле, у которого не установлен флаг «Внешнее соединение», система не сможет выполнить этот код и выдаст ошибку.
Посмотрим на алгоритм исправления:
#Если НЕ ВнешнееСоединение Тогда
// Код, который не должен выполняться при COM-подключении
// Например, вызов клиентских процедур или Сообщить()
#КонецЕсли
При работе через COM часто возникает ошибка: «Попытка передачи с клиента на сервер мутабельного значения». Это происходит, когда вы пытаетесь передать объект (например, ДокументОбъект) в процедуру общего модуля, который выполняется на сервере. Рассмотрим пример: внутри модуля объекта документа вызывается функция РасчетыСлужебный.ПолучитьИдентификатор(ЭтотОбъект). В режиме COM-соединения ЭтотОбъект является прокси-объектом, который нельзя просто так передать в серверный контекст.
Как это исправить: Вместо передачи самого объекта передавайте его ссылку или структуру данных. Если же код типовой и менять его нельзя, убедитесь, что все задействованные модули имеют флаг «Внешнее соединение», чтобы код выполнялся в том же контексте, не пытаясь пересечь границу «клиент-сервер» внутри COM-сессии.
В некоторых версиях платформы 8.3 наблюдались странные баги, когда использование русскоязычного метода Записать приводило к ошибкам в COM-соединении под SQL, в то время как англоязычный аналог работал корректно. Хотя это звучит как миф, разберем пример работающего кода:
// Вместо ДокОбъект.Записать(глCOMCоединение.РежимЗаписиДокумента.Проведение);
// Попробуйте использовать:
ДокОбъект.Write(глCOMCоединение.DocumentWriteMode.Posting);
Этот подход помогал на ранних релизах платформы 8.3.5 и 8.3.6 при специфических настройках региональных стандартов сервера.
Если причину найти не удается, необходимо включить отладку для внешних соединений. По умолчанию отладчик не «цепляет» сессии, созданные через V83.COMConnector.
Для активации отладки на сервере необходимо создать файл comcntrcfg.xml в каталоге conf (рядом с logcfg.xml) со следующим содержимым:
<config xmlns="http://v8.1c.ru/7.4/config/comcntrcfg">
<debugportal address="tcp://localhost" port="1560"/>
</config>
После этого в конфигураторе через меню «Отладка — Подключение» можно будет увидеть сеансы типа «Внешнее соединение» и установить в них точки останова, чтобы выяснить точное место возникновения исключения.
Проанализируем ситуацию стратегически: проведение тяжелых документов через COM-соединение в реальном времени — это всегда риск зависания сессий и проблем с блокировками. Опытные архитекторы рекомендуют следующую схему:
Это гарантирует стабильность работы и отсутствие проблем с контекстами COM-объектов.
Подводя итог, если вы столкнулись с невозможностью проведения документа через COM под SQL, первым делом проверьте флаги «Внешнее соединение» у общих модулей и права на последовательности. В 90% случаев проблема кроется именно в этих настройках.