В практике интеграции систем на платформе 1С:Предприятие 8 часто возникает задача: находясь в одной информационной базе (например, учетной УПП или ERP), программно создать объект в другой базе (например, в «1С:Документообороте») и сразу же открыть его форму на экране пользователя для ручного дозаполнения. При этом в открываемую форму крайне важно передать дополнительные параметры (например, контекст создания, режим открытия или служебные флаги).
На первый взгляд задача кажется тривиальной и решается через OLE-соединение V83.Application и метод ОткрытьФорму(). Однако разработчики регулярно сталкиваются с неочевидными ошибками преобразования типов и проблемами совместимости версий платформы. В этой статье мы подробно разберем причины возникновения этих ошибок и рассмотрим три надежных способа их решения.
Рассмотрим типичный сценарий, который на первый взгляд кажется логичным, но приводит к ошибке выполнения в базе-источнике:
// Пример НЕРАБОЧЕГО кода
V83appl = Новый COMОбъект("V83.Application");
Если V83appl.Connect(мояСтрокаСоединения) Тогда
// Создаем документ в базе-приемнике через COM
НовыйДокумент = V83appl.Документы.ВнутреннийДокумент.СоздатьДокумент();
НовыйДокумент.Наименование = "Служебная записка";
НовыйДокумент.Записать();
// Пытаемся передать параметры формы
ПараметрыФормы = Новый Структура; // Создается в локальном контексте!
ПараметрыФормы.Вставить("Ключ", НовыйДокумент.Ссылка);
ПараметрыФормы.Вставить("ТолькоЧтоСозданныйДокумент", Истина);
// Вызов приводит к ошибке преобразования типов!
V83appl.ОткрытьФорму("Документ.ВнутреннийДокумент.Форма.ФормаДокумента", ПараметрыФормы);
КонецЕсли;
Выясним причину сбоя. В приведенном примере объект ПараметрыФормы (типа Структура) создается в контексте базы-источника. Когда мы пытаемся передать эту структуру в метод ОткрытьФорму() COM-соединения, платформа базы-приемника не может корректно прочитать локальный объект 1С другой базы. Ссылочные типы данных внутри структуры (в данном случае НовыйДокумент.Ссылка, который в источнике виден как тип COMОбъект) также не могут быть обработаны механизмом сериализации COM «на лету».
Рассмотрим три способа решения этой проблемы, начиная с классического COM-подхода и заканчивая современными альтернативными техниками, не зависящими от версий платформы.
---
Чтобы избежать конфликта контекстов выполнения, структуру параметров и все ее составляющие необходимо инициализировать непосредственно внутри базы-приемника. Для этого используется метод OLE-системы NewObject() (или НовыйОбъект() в русскоязычном варианте).
Проанализируем правильный вариант реализации сценария:
// Пример РАБОЧЕГО кода через COM-соединение
V83appl = Новый COMОбъект("V83.Application");
Если V83appl.Connect(мояСтрокаСоединения) Тогда
// 1. Создаем и записываем документ в базе-приемнике
НовыйДокумент = V83appl.Документы.ВнутреннийДокумент.СоздатьДокумент();
НовыйДокумент.Наименование = "Интеграционный документ";
НовыйДокумент.Записать();
// Получаем ссылку на только что созданный документ в контексте приемника
СсылкаНаДокумент = НовыйДокумент.Ссылка;
// 2. Создаем структуру параметров формы непосредственно в удаленной базе!
ПараметрыФормыПриемника = V83appl.NewObject("Структура");
// Наполняем структуру параметрами
ПараметрыФормыПриемника.Вставить("Ключ", СсылкаНаДокумент);
ПараметрыФормыПриемника.Вставить("ТолькоЧтоСозданныйДокумент", Истина);
ПараметрыФормыПриемника.Вставить("РежимЧтения", Ложь);
// 3. Открываем форму, передавая "родную" структуру параметров базы-приемника
V83appl.ОткрытьФорму("Документ.ВнутреннийДокумент.Форма.ФормаДокумента", ПараметрыФормыПриемника);
КонецЕсли;
В данном случае метод V83appl.NewObject("Структура") гарантирует, что коллекция параметров будет создана в оперативной памяти процесса базы-приемника. Передаваемая в ключ структура полностью совместима с интерфейсными механизмами удаленной базы, и форма успешно откроется на экране пользователя.
---
Работа через COM-соединение V83.Application имеет критический недостаток — она требует запуска полноценного тяжелого процесса GUI удаленной базы из-под вызывающего приложения. На терминальных серверах это часто приводит к зависаниям и конфликтам разрядности (например, когда источник работает на 32-битной платформе, а приемник требует 64-битного окружения). Более того, если версии платформ баз отличаются (например, 8.3.10 и 8.3.14), зарегистрированный в реестре Windows OLE-сервер вернет ошибку «Несоответствие версий клиента и сервера».
Чтобы обойти эти ограничения, мы можем применить технологию внешних навигационных ссылок. Этот способ работает невероятно быстро, надежно и не требует администрирования реестра или COM+.
Разберем данный алгоритм по шагам:
V83.COMConnector, мы подключаемся к базе-приемнику исключительно для создания и записи объекта в базу данных (без отрисовки интерфейса).1cestart.exe) и откроет форму нужного объекта.Посмотрим на пример реализации этого метода:
// Используем быстрый COM-коннектор без интерфейса
Connector = Новый COMОбъект("V83.COMConnector");
БазаПриемник = Connector.Connect(мояСтрокаСоединения);
// Создаем и записываем документ
НовыйДок = БазаПриемник.Документы.ВнутреннийДокумент.СоздатьДокумент();
НовыйДок.Наименование = "Документ из внешней системы";
НовыйДок.Записать();
// Получаем строковое представление уникального идентификатора (GUID)
УИД_Строкой = БазаПриемник.String(НовыйДок.Ссылка.УникальныйИдентификатор());
// Формируем навигационную ссылку (для файлового или серверного варианта)
// Формат для сервера: e1c://server/ИмяСервера/ИмяБазы#e1cib/data/Документ.ВнутреннийДокумент?ref=УИД
СтрокаПодключения = мояСтрокаСоединения; // Например: "Srvr=""Server"";Ref=""Base"";"
// Парсим параметры строки подключения для формирования URL
ИмяСервера = "ServerName"; // Выделить программно из строки подключения
ИмяБазы = "BaseName"; // Выделить программно из строки подключения
НавигационнаяСсылка = "e1c://server/" + ИмяСервера + "/" + ИмяБазы
+ "#e1cib/data/Документ.ВнутреннийДокумент?ref=" + УИД_Строкой;
// Запускаем форму объекта в сеансе пользователя штатными средствами Windows
ЗапуститьПриложение(НавигационнаяСсылка);
Важное примечание: Если вам необходимо передать в открываемую форму дополнительные параметры, начиная с версии платформы 1С 8.3.19, вы можете добавлять пользовательские параметры непосредственно в навигационную ссылку (через символ &). На стороне базы-приемника в модуле управляемого приложения их можно перехватить в обработчике ОбработкаПереходаПоНавигационнойСсылке.
---
Если версия вашей платформы ниже 8.3.19, но вам все равно требуется передать специфические параметры (например, заполнить табличную часть при открытии или передать флаг инициализации бизнес-процесса), можно использовать запуск тонкого клиента через командную строку с параметром /C.
Этот способ гарантирует изоляцию сеансов пользователей на терминальном сервере и исключает проблемы с правами доступа к реестру Windows.
Рассмотрим схему реализации:
"C:\Program Files\1cv8\common\1cestart.exe" ENTERPRISE /S "Server\Base" /C "ИмяПараметраСхеме"
ПриНачалеРаботыСистемы считываем ПараметрЗапуска, парсим параметры и открываем форму нужного нам объекта с переданными аргументами.Посмотрим на пример кода парсинга параметров при старте системы базы-приемника:
Процедура ПриНачалеРаботыСистемы()
Если ЗначениеЗаполнено(ПараметрЗапуска) Тогда
// Предположим, параметры переданы в формате JSON: {"Action":"OpenDoc", "ID":"GUID_объекта", "Flag":true}
ПараметрыСтруктура = ДесериализоватьСтрокуJSON(ПараметрЗапуска);
Если ПараметрыСтруктура.Свойство("Action") И ПараметрыСтруктура.Action = "OpenDoc" Тогда
СсылкаНаОбъект = Справочники.ВнутренниеДокументы.ПолучитьСсылка(Новый УникальныйИдентификатор(ПараметрыСтруктура.ID));
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Ключ", СсылкаНаОбъект);
ПараметрыФормы.Вставить("ТолькоЧтоСозданныйДокумент", ПараметрыСтруктура.Flag);
ОткрытьФорму("Справочник.ВнутренниеДокументы.Форма.ФормаЭлемента", ПараметрыФормы);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Использование этого подхода позволяет полностью отказаться от нестабильной технологии OLE (V83.Application) в пользу стабильного и безопасного запуска тонких клиентов, минимизируя нагрузку на сервер и упрощая обновление платформы 1С.