При организации обмена данными между конфигурациями 1С (например, УТ 10.3 и БП 2.0) через COM-соединение разработчики часто сталкиваются с ситуацией: процесс выгрузки из базы-источника проходит успешно, счетчик выгруженных объектов заполнен, но в базе-приемнике счетчик загрузки равен нулю. При этом ручная загрузка того же файла через обработку УниверсальныйОбменДаннымиXML проходит без ошибок. Разберем подробно, почему так происходит и как правильно настроить программный обмен.
Рассмотрим стандартный сценарий. Программист пишет код в базе-источнике (УТ), который подключается к базе-приемнику (БП) через V83.COMConnector. Код создает временный файл в УТ, записывает туда XML-данные, а затем передает путь к этому файлу в COM-объект обработки загрузки в БП. Проблема кроется в разнице контекстов выполнения.
Когда мы вызываем метод ВыполнитьЗагрузку() через COM-объект, выполнение кода часто переходит на сторону сервера базы-приемника (если база клиент-серверная). Сервер 1С (служба ragent) работает под собственной учетной записью (обычно USR1CV8). Эта учетная запись "не видит" локальные пути вашего компьютера или временные папки вашего сеанса. В результате возникает ошибка доступа к файлу, которую не всегда видно в основном окне сообщений.
Проанализируем типичную ошибку из журнала регистрации, которая возникает в этот момент:
{Обработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(...)}: Ошибка при вызове метода контекста (ОткрытьФайл): Ошибка доступа к файлу 'C:\Users\ИмяПользователя\AppData\Local\Temp\v8_XXXX.xml'.
Самый эффективный способ решить проблему прав доступа — заставить базу-приемник саму создать путь для файла в том месте, куда у нее гарантированно есть доступ. Для этого мы будем использовать метод КаталогВременныхФайлов(), вызванный от лица COM-объекта.
Разберем правильный алгоритм реализации обмена:
ДвоичныеДанные на стороне источника.Рассмотрим пример кода, который решает эту задачу:
// Получаем данные выгрузки (например, из функции, возвращающей ДвоичныеДанные)
ДвоичныеДанные = ВыгрузитьНаСервереУТ();
// Создаем обработку загрузки внутри COM-объекта БазаБП
Обработка = БазаБП.Обработки.УниверсальныйОбменДаннымиXML.Создать();
// КРИТИЧЕСКИ ВАЖНЫЙ МОМЕНТ:
// Получаем путь к временной папке именно ТЕРМИНАЛА/СЕРВЕРА базы-приемника
ПутьКФайлуВПриемнике = БазаБП.КаталогВременныхФайлов() + "Обмен_С_УТ.xml";
// Записываем данные из источника в файл по пути, который понятен приемнику
ДвоичныеДанные.Записать(ПутьКФайлуВПриемнике);
// Настраиваем параметры обработки в БП
Обработка.РежимОбмена = "Загрузка";
Обработка.ИмяФайлаОбмена = ПутьКФайлуВПриемнике;
Обработка.ОткрытьФайлЗагрузки(Истина);
Обработка.АрхивироватьФайл = Ложь;
// Запускаем процесс
Обработка.ВыполнитьЗагрузку();
Сообщить("Загружено объектов: " + Обработка.мСчетчикЗагруженныхОбъектов);
Если вы хотите избежать промежуточного сохранения файлов на диск, можно использовать механизм непосредственного чтения. В обработке УниверсальныйОбменДаннымиXML (версии 2.1.7 и выше) предусмотрено свойство НепосредственноеЧтениеВИБПриемнике.
В этом режиме база-источник сама инициирует COM-подключение к приемнику и передает данные порциями напрямую в объекты. Это избавляет от проблем с правами на файловую систему. Рассмотрим, как настроить этот режим:
Обработка = Обработки.УниверсальныйОбменДаннымиXML.Создать();
Обработка.РежимОбмена = "Выгрузка";
Обработка.НепосредственноеЧтениеВИБПриемнике = Истина;
// Настройка подключения к базе-приемнику
Обработка.ТипИнформационнойБазыДляПодключения = Ложь; // Ложь для серверной, Истина для файловой
Обработка.ИмяСервераИнформационнойБазыДляПодключения = "ИмяСервера";
Обработка.ИмяИнформационнойБазыНаСервереДляПодключения = "ИмяБазыБП";
Обработка.ПользовательИнформационнойБазыДляПодключения = "Админ";
Обработка.ПарольИнформационнойБазыДляПодключения = "Пароль";
// Загружаем правила обмена (из макета или файла)
Обработка.ИмяФайлаПравилОбмена = ПутьКПравилам;
Обработка.ЗагрузитьПравилаОбмена();
// Выполняем обмен
Обработка.ВыполнитьВыгрузку();
Важно: При таком подходе обработка должна физически находиться и запускаться в базе-источнике, а все настройки подключения указываются в её реквизитах.
При работе с COM-соединениями существуют специфические системные нюансы, которые могут прервать обмен даже при правильном коде:
comcntr.dll в "Службах компонентов" Windows (DCOM) как отдельное приложение COM+. Это позволит запускать COM-соединение в изолированном процессе dllhost.exe.БазаБП = Неопределено;.Предупреждение() или Вопрос(). В режиме COM-соединения некому нажать на кнопку, и процесс просто зависнет.ФлагОшибки. Если оно истинно, выводите сообщения из приемника через метод БазаБП.ПолучитьСообщенияПользователю().Проанализировав ситуацию и применив метод записи файла во временный каталог базы-приемника или режим непосредственного чтения, вы обеспечите стабильный и прозрачный обмен данными между вашими конфигурациями 1С.