Работа с внешними приложениями через механизм COM-соединения — одна из самых распространенных задач в 1С, особенно когда речь идет об импорте данных из электронных таблиц. Однако многие разработчики сталкиваются с неприятной ситуацией: после завершения работы обработки в диспетчере задач Windows продолжают висеть процессы Excel.exe. Это не только потребляет оперативную память, но и может привести к блокировке файлов или невозможности запуска новых сессий Excel при достижении лимита. В этой статье мы подробно разберем, почему так происходит и как гарантированно закрыть процесс.
Рассмотрим ситуацию, с которой столкнулся автор темы. Зачастую корень проблемы кроется в невнимательности при написании кода. Проанализируем фрагмент, который привел к «подвисанию» процесса:
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ИмяФайла);
Исключение
// Обработка ошибки
КонецПопытки;
// ... какой-то код ...
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ИмяФайла);
Исключение
// Обработка ошибки
КонецПопытки;
В данном примере разработчик дважды инициализирует переменную Excel новым COM-объектом. При втором вызове Новый COMОбъект ссылка на первый экземпляр приложения теряется, но сам процесс в операционной системе остается активным. Поскольку 1С больше «не видит» первый объект, она не может отправить ему команду на закрытие. Вывод: всегда следите за тем, чтобы объект создавался единожды, либо корректно закрывался перед повторным использованием переменной.
Для того чтобы Excel корректно завершил свою работу, недостаточно просто обнулить переменную. Процесс закрытия должен быть многоступенчатым. Разберем по шагам, как это реализовать в коде 1С:
Quit().Неопределено.Пример надежного кода для завершения работы:
Попытка
Если Excel <> Неопределено Тогда
Excel.DisplayAlerts = Ложь; // Отключаем системные сообщения Excel
Excel.Workbooks.Close();
Excel.Quit();
Excel = 0;
КонецЕсли;
Исключение
Excel = 0; // В случае ошибки просто обнуляем ссылку
КонецПопытки;
Важно помнить: метод Excel.Quit() — это лишь «просьба» к приложению закрыться. Если в этот момент открыто модальное окно (например, с вопросом о сохранении файла), Excel будет ждать ответа пользователя и процесс останется в памяти. Именно поэтому использование DisplayAlerts = Ложь является критически важным.
Выясним причину, по которой даже после Quit() процесс может не исчезнуть. Механизм COM работает на основе счетчика ссылок. Процесс завершается только тогда, когда счетчик равен нулю. Если вы обращаетесь к ячейкам или листам напрямую через длинные цепочки, 1С создает промежуточные неявные объекты.
Например, в строке Значение = Excel.Workbooks(1).Sheets(1).Cells(1,1).Value; создаются объекты для книги, листа и ячейки. Рекомендуется назначать каждый уровень отдельной переменной и очищать их в обратном порядке:
Книги = Excel.Workbooks;
Книга = Книги.Open(ИмяФайла);
Лист = Книга.Sheets(1);
// ... работа с листом ...
Лист = Неопределено;
Книга.Close(Ложь);
Книга = Неопределено;
Книги = Неопределено;
Excel.Quit();
Excel = Неопределено;
Если штатные методы не помогают (например, при критическом сбое самого Excel), можно воспользоваться средствами операционной системы. Посмотрим на пример использования системной утилиты taskkill через объект WScript.Shell:
WshShell = Новый COMОбъект("WScript.Shell");
// Ключ /f означает принудительное завершение, /im - поиск по имени процесса
WshShell.Run("taskkill /f /im excel.exe", 0, Истина);
Внимание: этот метод крайне радикален. Он закроет все запущенные процессы Excel на компьютере. Если в этот момент менеджер заполняет важный отчет вручную, его данные будут потеряны. Используйте этот способ только на серверах в ночное время или если вы уверены, что Excel используется только вашей обработкой.
Проанализируем ситуацию, когда обработка запускается в фоновом задании на сервере. Часто Excel «виснет» из-за отсутствия необходимых системных папок в профиле пользователя, под которым работает служба 1С. Для корректной работы COM-объекта системе требуются папки Desktop.
Попробуйте вручную создать следующие директории:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopЭто старый, но до сих пор актуальный «лайфхак» для серверных ОС (Windows Server 2012/2016/2019), который решает проблемы инициализации графического интерфейса Excel в невидимом режиме.
Рассмотрим подробнее: стоит ли вообще использовать COM? Начиная с версии платформы 8.3.6, в 1С встроен мощный инструмент для работы с файлами Excel без установки самого офисного пакета. Это объект ТабличныйДокумент.
Разберем пример чтения файла современным способом:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЛистовТабличногоДокумента.ЗагружатьЛистыПоОтдельности);
Исключение
Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Теперь данные доступны в ТабДок как в обычной таблице 1С
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Артикул = ТабДок.Область(НомерСтроки, 1).Текст;
// ... логика загрузки ...
КонецЦикла;
Использование Прочитать() полностью исключает проблему «зависших» процессов, так как Excel вообще не запускается. Это работает быстрее, стабильнее и не требует лицензии Microsoft Office на сервере.
Подведем итоги: для стабильной работы необходимо избегать повторных инициализаций объектов в коде, всегда использовать Try...Finally (Попытка...Исключение) для гарантированного закрытия через Quit(), а в идеале — переходить на встроенные средства платформы 1С для работы с форматом XLSX.