Как вызвать внешнюю обработку 1С из C# через COM-соединение и исправить ошибку создания объекта?

Программист 1С v8.3 (Управляемые формы) 1С:Розница IT и автоматизация бизнеса
← На главную

При интеграции приложений на платформе .NET (C#) с «1С:Предприятие» нередко возникает задача выноса специфической логики во внешнюю обработку (файл с расширением .epf). Это особенно актуально, когда используется базовая конфигурация или конфигурация, находящаяся на полной поддержке поставщика, в которую нельзя вносить изменения напрямую.

Однако при попытке инициализировать обработку через менеджер внешних обработок разработчики часто сталкиваются с ошибкой «Ссылка на объект не указывает на экземпляр объекта» (NullReferenceException) непосредственно на этапе выполнения метода ВнешниеОбработки.Создать(). Разберем по шагам, почему возникает эта ошибка, как настроить платформу 1С и как правильно вызывать методы внешней обработки из C#.

Выясним причину ошибки: механизм защиты от опасных действий

Проанализируем типовую ситуацию. Подключение к информационной базе проходит успешно, запросы и выборки по справочникам отрабатывают без нареканий, но следующая строка на C# приводит к падению программы:


dynamic extProcess = com1Cserv.ВнешниеОбработки.Создать(@"D:\1C BASE\OtherExtCodes\SetRegisterRecord.epf", false);

Выясним причину такого поведения. Начиная с версии платформы 8.3.9, в 1С реализован встроенный механизм безопасности — «Защита от опасных действий». При попытке программного или интерактивного открытия внешнего файла платформе требуется запросить у пользователя подтверждение на открытие потенциально опасного содержимого.

В сеансе COM-соединения (объект V83.COMConnector) графический интерфейс пользователя полностью отсутствует. Так как модальное диалоговое окно подтверждения не может быть выведено на экран, среда исполнения 1С прерывает операцию или возвращает пустое значение. В приложении на C# тип dynamic пытается разрешить обращение к несуществующему объекту, из-за чего выбрасывается исключение NullReferenceException.

Способ 1. Отключение предупреждений в конфигурационном файле conf.cfg

Рассмотрим первый вариант решения проблемы, который позволяет отключить предупреждения на уровне конфигурационных файлов сервера или локального клиента 1С. Этот подход удобен при разработке и отладке на выделенном рабочем месте.

  1. Найдем файл конфигурации платформы conf.cfg. Обычно он располагается в каталоге установки платформы (например, C:\Program Files\1cv8\conf\conf.cfg) или в общесистемном каталоге настроек.
  2. Добавим в данный файл директиву отключения предупреждений для всех баз: DisableUnsafeActionProtection=.*
  3. Если необходимо отключить защиту только для определенной базы данных, в параметре можно указать конкретное регулярное выражение с путем к базе или ее строкой соединения.

Способ 2. Отключение защиты в свойствах пользователя информационной базы

Более точечный и безопасный метод — отключить защиту для конкретного сервисного пользователя, от имени которого выполняется COM-соединение из C#. Разберем, как это сделать:

  1. Откроем информационную базу в режиме «Конфигуратор» под учетной записью с административными правами.
  2. Перейдем в главное меню: Администрирование → Пользователи.
  3. Найдем пользователя, под которым происходит авторизация через COM-соединение, и откроем его свойства.
  4. На вкладке основных параметров снимем флаг «Защита от опасных действий».
  5. Сохраним изменения.

Если требуется отключить эту проверку программно из встроенного языка 1С, используем свойство пользователя информационной базы:


ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени("ComUser");
ПользовательИБ.ЗащитаОтОпасныхДействий.ПредупреждатьОбОпасныхДействиях = Ложь;
ПользовательИБ.Записать();

Способ 3. Использование метода «Подключить» менеджера внешних обработок

Вместо непосредственного вызова метода Создать() можно сначала выполнить регистрацию обработки во внутреннем хранилище сеанса с помощью метода Подключить(), явно передав флаг отключения безопасного режима:


string path = @"D:\1C BASE\OtherExtCodes\SetRegisterRecord.epf";
string extName = com1Cserv.ВнешниеОбработки.Подключить(path, "МояВнешняяОбработка", false);
dynamic extProcess = com1Cserv.ВнешниеОбработки.Создать(extName, false);

Метод Подключить() связывает внешний файл с уникальным именем во временном контексте базы данных, после чего создание объекта по имени происходит штатно.

Полный пример подключения и вызова логики на C#

Посмотрим на пример законченного кода на C#, который подключается к базе, создает экземпляр внешней обработки, выполняет экспортную функцию и корректно освобождает системные ресурсы COM:


using System;
using System.Runtime.InteropServices;

namespace Integration1C
{
    class Program
    {
        static void Main(string[] args)
        {
            Type comType = Type.GetTypeFromProgID("V83.COMConnector");
            dynamic connector = Activator.CreateInstance(comType);

            string connectionString = @"File=""D:\1C BASE\BaseRoznica"";Usr=""ComUser"";Pwd=""Password123"";";
            dynamic com1Cserv = null;
            dynamic extProcess = null;

            try
            {
                com1Cserv = connector.Connect(connectionString);

                string path = @"D:\1C BASE\OtherExtCodes\SetRegisterRecord.epf";
                // Создаем экземпляр обработки (второй параметр - безопасный режим)
                extProcess = com1Cserv.ВнешниеОбработки.Создать(path, false);

                // Вызываем экспортную функцию из модуля объекта внешней обработки
                dynamic result = extProcess.ВыполнитьДействие();
                Console.WriteLine("Результат из 1С: " + result);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Ошибка выполнения: " + ex.Message);
            }
            finally
            {
                // Обязательно освобождаем COM-объекты для исключения зависания процессов
                if (extProcess != null)
                {
                    Marshal.ReleaseComObject(extProcess);
                }
                if (com1Cserv != null)
                {
                    Marshal.ReleaseComObject(com1Cserv);
                }
                if (connector != null)
                {
                    Marshal.ReleaseComObject(connector);
                }
            }
        }
    }
}

Важные требования к модулю внешней обработки

При вызове обработки из внешнего соединения действуют ограничения серверного контекста платформы 1С:

  1. Только модуль объекта: COM-соединение не имеет экранных форм. Весь исполняемый код должен быть размещен строго в Модуле объекта обработки, а не в модулях форм или команд.
  2. Экспорт процедур и функций: Все вызываемые из C# методы обязаны иметь директиву Экспорт:
    
    Функция ВыполнитьДействие() Экспорт
        // Серверная логика обработки данных
        Возврат "Успешно";
    КонецФункции
    
  3. Отсутствие клиентских методов: Внутри вызываемого кода нельзя использовать интерактивные функции (такие как Предупреждение(), Вопрос(), ОткрытьФорму()) и директивы компиляции &НаКлиенте. Их вызов в контексте COM приведет к аварийной остановке выполнения.

Альтернатива: справочник «Дополнительные отчеты и обработки»

Если в конфигурации используется библиотека стандартных подсистем (БСП), как в конфигурации «1С:Розница», не обязательно хранить файл .epf на локальном диске в файловой системе. Обработку можно зарегистрировать непосредственно в справочнике ДополнительныеОтчетыИОбработки через пользовательский интерфейс 1С.

В этом случае логика обработки вызывается через стандартный программный интерфейс БСП:


dynamic refProcessing = com1Cserv.Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("ИнтеграцияСклады");
dynamic objectProcessing = com1Cserv.ДополнительныеОтчетыИОбработки.ОбъектВнешнейОбработки(refProcessing);
objectProcessing.ВыполнитьДействие();

Такой подход упрощает администрирование: обновление логики обработки выполняется непосредственно внутри базы данных без необходимости заменять файлы на сервере или рабочей станции.

← На главную