При автоматизации рутинных процессов в 1С разработчики часто прибегают к выгрузке или загрузке данных из файлов Microsoft Excel. Для этого традиционно используется COM-соединение. На локальном компьютере программиста код отрабатывает идеально, но при переносе решения на сервер и настройке автоматического запуска через планировщик задач (Task Scheduler) или регламентные задания фоновые процессы начинают аварийно завершаться на строке инициализации COM-объекта.
В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем внутренние механизмы операционной системы Windows и рассмотрим по шагам несколько эффективных способов решения проблемы.
Для того чтобы понять суть проблемы, проанализируем ситуацию с точки зрения безопасности операционной системы Windows Server. Начиная с версии Windows Server 2008, Microsoft внедрила строгую политику безопасности — изоляцию Сессии 0 (Session 0 Isolation).
Все службы Windows, а также процессы, запускаемые планировщиком задач в режиме «Выполнять вне зависимости от того, вошел ли пользователь в систему» (Run whether user is logged on or not), запускаются в неинтерактивной Сессии 0. В этой сессии физически отсутствует графический интерфейс (Desktop), а также привычное окружение пользователя (профиль, реестр, папки автозагрузки).
Программа Microsoft Excel изначально разрабатывалась как настольное (интерактивное) приложение. При запуске через Новый COMОбъект("Excel.Application") процесс EXCEL.EXE пытается инициализировать графическую оболочку, прочитать настройки принтера по умолчанию, обратиться к ветке реестра текущего пользователя и проверить наличие папки рабочего стола (Desktop). Не найдя этих компонентов в Сессии 0, процесс Excel либо аварийно завершается, либо «зависает» в памяти навсегда, потребляя ресурсы процессора.
Рассмотрим подробнее основные способы преодоления этой проблемы — от простых системных «костылей» до фундаментальной настройки безопасности DCOM.
Это самый быстрый и проверенный временем способ заставить Excel работать в фоновом режиме. Когда процесс инициализируется под системной учетной записью или в неинтерактивной сессии, он ищет папку Desktop в профиле системы. Если этой папки нет, инициализация прерывается.
Разберем по шагам, как решить эту проблему вручную:
C:\Windows\SysWOW64\config\systemprofile
Desktop. Если его нет, создайте папку вручную. Имя папки должно быть написано строго на английском языке с заглавной буквы.C:\Windows\System32\config\systemprofile
Desktop и здесь. Даже если ваша операционная система 64-битная, компоненты Microsoft Office или сама платформа 1С могут быть 32-битными, поэтому папка необходима в обоих каталогах.Desktop, перейдите на вкладку «Безопасность» (Security) и предоставьте полные права (Full Control) той учетной записи, от имени которой запускается задача в планировщике задач Windows (или пользователю, под которым запущена служба сервера 1С:Предприятие).После создания этих папок Excel получит фиктивный рабочий стол для своей инициализации, и COM-объект будет создаваться успешно.
Иногда создание папок не помогает из-за жестких ограничений безопасности распределенной объектной модели (DCOM). Операционная система может блокировать запуск COM-серверов из неинтерактивных сессий. Нам потребуется скорректировать параметры запуска Microsoft Excel через системную утилиту.
Рассмотрим по шагам процесс настройки:
Win + R, введите команду dcomcnfg и нажмите Enter. Откроется консоль «Службы компонентов».mmc comexp.msc /32
Этот шаг привязывает запуск COM-объекта Excel к конкретному пользователю, у которого гарантированно есть рабочий профиль в системе, что решает большинство проблем совместимости.
Посмотрим на настройки самой задачи в Task Scheduler. Если вы запускаете батник, запускающий 1С, поведение системы сильно зависит от параметров безопасности задачи.
Проанализируем две стратегии настройки вкладки «Общие» (General):
SYSTEM (Система). Настройте запуск задачи от имени специально созданного локального или доменного пользователя, входящего в группу администраторов сервера.Если служба безопасности вашей компании наотрез отказывается вносить изменения в папки systemprofile и настраивать DCOM, можно прибегнуть к программному обходному пути.
Мы можем настроить автоматический вход пользователя в систему при старте сервера (Autologon), а запуск батника поместить в автозагрузку пользователя или в планировщик с признаком интерактивного выполнения. Это гарантирует, что 1С запустится в полноценном пользовательском сеансе со всеми правами на инициализацию графических интерфейсов Excel.
Еще одна неочевидная проблема кроется в разнице разрядностей 1С и Microsoft Office. Если сервер 1С работает под управлением 64-битного процесса, а на сервере установлен 32-битный MS Excel, прямой вызов Новый COMОбъект("Excel.Application") завершится ошибкой «Интерфейс не поддерживается».
Для исправления этой ситуации рекомендуется придерживаться правила: разрядность платформы 1С и пакета Microsoft Office на сервере должна совпадать. Если это невозможно, проблему совместимости разрядностей решают созданием COM+ приложения-обертки (через службу компонентов Windows), которое выступает в роли посредника (прокси) между 32-битным Excel и 64-битной платформой 1С.
Даже при успешной инициализации COM-объекта разработчики часто сталкиваются с проблемой «зависания» процессов EXCEL.EXE в диспетчере задач сервера. Это происходит из-за того, что 1С не освобождает ссылки на объекты Excel должным образом.
Рассмотрим пример правильного и безопасного написания кода для работы с COM-объектом в 1С:
Попытка
Эксель = Новый COMОбъект("Excel.Application");
Исключение
ЗаписьЖурналаРегистрации("Интеграция.Excel",
УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось запустить Excel: " + ОписаниеОшибки());
ВызватьИсключение "Ошибка инициализации COM-объекта Excel. Проверьте системные настройки.";
КонецПопытки;
Попытка
// Делаем окно Excel невидимым для фонового режима
Эксель.Visible = Ложь;
Эксель.DisplayAlerts = Ложь; // Отключаем все предупреждения и диалоговые окна
// Открываем книгу для работы
Книга = Эксель.Workbooks.Open(ПутьКФайлу);
Лист = Книга.Sheets(1);
// Пример чтения данных
ЗначениеЯчейки = Лист.Cells(1, 1).Value;
// Закрываем книгу с сохранением изменений (или без)
Книга.Close(Ложь);
Исключение
// В случае ошибки обязательно пытаемся корректно закрыть Excel
Если ЗначениеЗаполнено(Эксель) Тогда
Эксель.Quit();
Эксель = Неопределено;
КонецЕсли;
ЗаписьЖурналаРегистрации("Интеграция.Excel",
УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при обработке файла: " + ОписаниеОшибки());
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
// Корректное завершение работы в штатном режиме
Эксель.Quit();
Эксель = Неопределено;
Важное правило: Обратите внимание, что в конце работы мы обязательно вызываем метод Quit() у объекта Excel, а затем явно присваиваем переменной значение Неопределено. Это гарантирует своевременное уничтожение COM-объекта в операционной системе и предотвращает утечку оперативной памяти на сервере.
Если ваша задача состоит исключительно в формировании файлов отчетов, рассмотрите возможность полного отказа от COM-технологий. Платформа 1С:Предприятие 8.3 обладает встроенными механизмами для сохранения табличных документов в формате XLSX без использования стороннего программного обеспечения:
ТабДок = Новый ТабличныйДокумент;
// Заполняем табличный документ данными...
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Этот метод работает на любой операционной системе (включая Linux-серверы), выполняется в разы быстрее, абсолютно стабилен в фоновом режиме и не требует установки Microsoft Office на сервере.