При разработке механизмов формирования печатных форм или отчетов с использованием Microsoft Office Word через COM-соединение программисты 1С часто сталкиваются с крайне неприятной проблемой. Код, который безошибочно выполняется в режиме пошаговой отладки, при обычном запуске (по клавише F5) неожиданно завершается аварийно. Платформа выдает ошибку вида "Ошибка совместного доступа к файлу" на строке инициализации двоичных данных или при попытке переместить/удалить временный файл.
В этой статье мы подробно разберем, почему возникает данная коллизия, как операционная система взаимодействует с COM-серверами, и рассмотрим надежные программные методы обхода этой ошибки, которые гарантируют стабильную работу системы под любыми нагрузками.
Для того чтобы понять природу этой ошибки, проанализируем поведение операционной системы Windows при работе с COM-объектом Word.Application. Когда мы вызываем метод Quit() у объекта Word, 1С посылает операционной системе команду закрыть приложение WINWORD.EXE. Однако этот процесс происходит асинхронно.
Это означает следующее:
Новый ДвоичныеДанные(...)) пытается открыть этот же файл для чтения.WINWORD.EXE еще не завершил выгрузку из оперативной памяти и все еще удерживает монопольный дескриптор (блокировку) на файл. В результате ОС запрещает платформе 1С доступ, и мы получаем ошибку совместного доступа.Почему же в отладчике все работает? Ответ прост: пока разработчик анализирует состояние переменных в конфигураторе и нажимает клавишу перехода к следующей строке (F10/F11), проходит как минимум несколько сотен миллисекунд. Этого времени операционной системе более чем достаточно, чтобы полностью закрыть процесс WINWORD.EXE, выгрузить его из памяти и снять все блокировки с временного файла.
Ниже мы подробно разберем три основных способа решения этой проблемы программным путем.
---
Часто разработчики ограничиваются лишь вызовом метода Quit() для глобального COM-объекта. Однако в памяти 1С могут оставаться неявные ссылки на дочерние объекты (такие как Документ, Параграфы, Таблицы и т.д.). Пока сборщик мусора 1С принудительно не очистит эти переменные, дескриптор файла может оставаться занятым.
Рассмотрим правильную последовательность закрытия объектов. Нам необходимо закрывать их строго в обратном порядке их создания и явно присваивать переменным значение Неопределено. Это заставит платформу 1С немедленно разорвать связь с COM-сервером.
Применим этот подход на практике. Посмотрим на пример кода:
// Сохраняем документ перед закрытием
Документ.SaveAs(ИмяВременногоФайла);
// 1. Явно закрываем сам документ Word.
// Параметр "0" означает "wdDoNotSaveChanges" (не сохранять изменения при закрытии, так как мы уже сохранились выше)
Документ.Close(0);
Документ = Неопределено;
// 2. Закрываем само приложение Word
Word.Quit();
Word = Неопределено;
// 3. Вызываем принудительный сбор мусора (опционально, для ускорения освобождения памяти)
ВызватьСистемнуюОперацию("GarbageCollect"); // Если применимо в контексте
Этот способ значительно снижает вероятность возникновения блокировки, однако на медленных компьютерах или при высокой загрузке сервера Windows все равно может не успеть закрыть процесс вовремя. Поэтому перейдем к более отказоустойчивому решению.
---
Наиболее надежным промышленным решением является написание алгоритма "мягкого ожидания". Вместо того чтобы сразу пытаться прочитать файл и падать с ошибкой, мы завернем чтение двоичных данных в цикл с попыткой-исключением. Если файл заблокирован, 1С сделает небольшую паузу и попробует снова.
Проанализируем пример реализации такого ожидания:
ДвоичныйФайл = Неопределено;
МаксимальноеКоличествоПопыток = 15;
ИнтервалОжиданияСекунд = 1;
Для НомерПопытки = 1 По МаксимальноеКоличествоПопыток Цикл
Попытка
// Пытаемся прочитать файл в двоичные данные.
// Если файл заблокирован операционной системой, управление сразу перейдет в блок "Исключение"
ДвоичныйФайл = Новый ДвоичныеДанные(ИмяВременногоФайла);
// Если чтение прошло успешно, немедленно прерываем цикл ожидания
Прервать;
Исключение
// Если произошла ошибка доступа, ждем некоторое время и пробуем снова
Если НомерПопытки < МаксимальноеКоличествоПопыток Тогда
// Реализация паузы в 1 секунду без сильного зависания интерфейса
// Для этого можно использовать системную утилиту "timeout" или "ping" через КомандаСистемы
СтрокаЗапуска = "timeout /T " + СокрЛП(ИнтервалОжиданияСекунд) + " /nobreak";
КомандаСистемы(СтрокаЗапуска, Ложь); // Ложь - чтобы окно консоли не мелькало перед пользователем
КонецЕсли;
КонецПопытки;
КонецЦикла;
// Проверяем, удалось ли нам в итоге получить доступ к файлу
Если ДвоичныйФайл = Неопределено Тогда
ВызватьИсключение "Не удалось получить доступ к файлу '" + ИмяВременногоФайла + "' после закрытия MS Word. Файл заблокирован операционной системой.";
КонецЕсли;
Данный подход гарантирует, что даже если компьютер сильно нагружен или файл имеет большой объем, система дождется его освобождения и продолжит работу без аварийного завершения сеанса пользователя.
---
Иногда виновником блокировки файлов становится не сам пакет MS Office, а установленный на сервере или рабочей станции антивирус. Работает это следующим образом:
WINWORD.EXE создает и модифицирует файл в каталоге временных файлов пользователя (Temp).Решение проблемы на уровне администрирования: добавьте каталог временных файлов пользователей 1С (обычно расположенный по пути C:\Users\<ИмяПользователя>\AppData\Local\Temp\) в список исключений (белый список) вашего антивирусного программного обеспечения. Это полностью уберет сторонние задержки при освобождении дисковых ресурсов.
---
Использование COM-объектов семейства Microsoft Office (Word.Application, Excel.Application) в среде 1С считается устаревшим подходом и не рекомендуется для использования в современных конфигурациях, особенно на стороне сервера 1С. Разберем основные причины:
WINWORD.EXE остаются висеть в памяти сервера «призраками», накапливаясь со временем и полностью забивая оперативную память сервера.Альтернативный вариант решения задачи: Современный формат файлов Word (.docx) представляет собой обычный ZIP-архив, внутри которого находятся XML-файлы с разметкой текста и стилей. Платформа 1С содержит мощные встроенные механизмы работы со встроенными объектами ZIP и XML. Вы можете использовать готовые открытые библиотеки или встроенные средства 1С для программного формирования документов Word без запуска тяжелого стороннего приложения WINWORD.EXE. Это обеспечит колоссальный прирост производительности и абсолютную кроссплатформенность вашего решения.