Как исправить ошибку совместного доступа к файлу при работе с COM-объектом Word в 1С?

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

При разработке механизмов формирования печатных форм или отчетов с использованием Microsoft Office Word через COM-соединение программисты 1С часто сталкиваются с крайне неприятной проблемой. Код, который безошибочно выполняется в режиме пошаговой отладки, при обычном запуске (по клавише F5) неожиданно завершается аварийно. Платформа выдает ошибку вида "Ошибка совместного доступа к файлу" на строке инициализации двоичных данных или при попытке переместить/удалить временный файл.

В этой статье мы подробно разберем, почему возникает данная коллизия, как операционная система взаимодействует с COM-серверами, и рассмотрим надежные программные методы обхода этой ошибки, которые гарантируют стабильную работу системы под любыми нагрузками.

Выясняем причину: почему в отладчике все работает, а в реальном времени — нет?

Для того чтобы понять природу этой ошибки, проанализируем поведение операционной системы Windows при работе с COM-объектом Word.Application. Когда мы вызываем метод Quit() у объекта Word, 1С посылает операционной системе команду закрыть приложение WINWORD.EXE. Однако этот процесс происходит асинхронно.

Это означает следующее:

  1. Платформа 1С отправляет команду закрытия и, не дожидаясь физического завершения процесса в ОС, мгновенно переходит к выполнению следующей строки кода.
  2. В этот же микросекундный момент следующая строка кода (например, Новый ДвоичныеДанные(...)) пытается открыть этот же файл для чтения.
  3. Операционная система Windows видит, что процесс WINWORD.EXE еще не завершил выгрузку из оперативной памяти и все еще удерживает монопольный дескриптор (блокировку) на файл. В результате ОС запрещает платформе 1С доступ, и мы получаем ошибку совместного доступа.

Почему же в отладчике все работает? Ответ прост: пока разработчик анализирует состояние переменных в конфигураторе и нажимает клавишу перехода к следующей строке (F10/F11), проходит как минимум несколько сотен миллисекунд. Этого времени операционной системе более чем достаточно, чтобы полностью закрыть процесс WINWORD.EXE, выгрузить его из памяти и снять все блокировки с временного файла.

Ниже мы подробно разберем три основных способа решения этой проблемы программным путем.

---

Способ 1. Правильное последовательное закрытие и освобождение COM-объектов

Часто разработчики ограничиваются лишь вызовом метода Quit() для глобального COM-объекта. Однако в памяти 1С могут оставаться неявные ссылки на дочерние объекты (такие как Документ, Параграфы, Таблицы и т.д.). Пока сборщик мусора 1С принудительно не очистит эти переменные, дескриптор файла может оставаться занятым.

Рассмотрим правильную последовательность закрытия объектов. Нам необходимо закрывать их строго в обратном порядке их создания и явно присваивать переменным значение Неопределено. Это заставит платформу 1С немедленно разорвать связь с COM-сервером.

Применим этот подход на практике. Посмотрим на пример кода:


// Сохраняем документ перед закрытием
Документ.SaveAs(ИмяВременногоФайла);

// 1. Явно закрываем сам документ Word. 
// Параметр "0" означает "wdDoNotSaveChanges" (не сохранять изменения при закрытии, так как мы уже сохранились выше)
Документ.Close(0); 
Документ = Неопределено;

// 2. Закрываем само приложение Word
Word.Quit();
Word = Неопределено;

// 3. Вызываем принудительный сбор мусора (опционально, для ускорения освобождения памяти)
ВызватьСистемнуюОперацию("GarbageCollect"); // Если применимо в контексте

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

---

Способ 2. Реализация цикла ожидания (тайм-аут) освобождения файла

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

Проанализируем пример реализации такого ожидания:


ДвоичныйФайл = Неопределено;
МаксимальноеКоличествоПопыток = 15;
ИнтервалОжиданияСекунд = 1;

Для НомерПопытки = 1 По МаксимальноеКоличествоПопыток Цикл
    Попытка
        // Пытаемся прочитать файл в двоичные данные. 
        // Если файл заблокирован операционной системой, управление сразу перейдет в блок "Исключение"
        ДвоичныйФайл = Новый ДвоичныеДанные(ИмяВременногоФайла);
        
        // Если чтение прошло успешно, немедленно прерываем цикл ожидания
        Прервать;
    Исключение
        // Если произошла ошибка доступа, ждем некоторое время и пробуем снова
        Если НомерПопытки < МаксимальноеКоличествоПопыток Тогда
            
            // Реализация паузы в 1 секунду без сильного зависания интерфейса
            // Для этого можно использовать системную утилиту "timeout" или "ping" через КомандаСистемы
            СтрокаЗапуска = "timeout /T " + СокрЛП(ИнтервалОжиданияСекунд) + " /nobreak";
            КомандаСистемы(СтрокаЗапуска, Ложь); // Ложь - чтобы окно консоли не мелькало перед пользователем
            
        КонецЕсли;
    КонецПопытки;
КонецЦикла;

// Проверяем, удалось ли нам в итоге получить доступ к файлу
Если ДвоичныйФайл = Неопределено Тогда
    ВызватьИсключение "Не удалось получить доступ к файлу '" + ИмяВременногоФайла + "' после закрытия MS Word. Файл заблокирован операционной системой.";
КонецЕсли;

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

---

Способ 3. Учет влияния антивирусного программного обеспечения

Иногда виновником блокировки файлов становится не сам пакет MS Office, а установленный на сервере или рабочей станции антивирус. Работает это следующим образом:

  1. Процесс WINWORD.EXE создает и модифицирует файл в каталоге временных файлов пользователя (Temp).
  2. При закрытии документа антивирусный монитор (файловый сканер в реальном времени) фиксирует изменение файла и мгновенно перехватывает его для проверки на наличие вредоносного кода.
  3. В этот микроскопический промежуток времени антивирус устанавливает свою собственную блокировку совместного доступа к файлу.
  4. Платформа 1С пытается прочитать файл и получает отказ со стороны ОС.

Решение проблемы на уровне администрирования: добавьте каталог временных файлов пользователей 1С (обычно расположенный по пути C:\Users\<ИмяПользователя>\AppData\Local\Temp\) в список исключений (белый список) вашего антивирусного программного обеспечения. Это полностью уберет сторонние задержки при освобождении дисковых ресурсов.

---

Архитектурная рекомендация: почему стоит отказаться от COM-соединений?

Использование COM-объектов семейства Microsoft Office (Word.Application, Excel.Application) в среде 1С считается устаревшим подходом и не рекомендуется для использования в современных конфигурациях, особенно на стороне сервера 1С. Разберем основные причины:

Альтернативный вариант решения задачи: Современный формат файлов Word (.docx) представляет собой обычный ZIP-архив, внутри которого находятся XML-файлы с разметкой текста и стилей. Платформа 1С содержит мощные встроенные механизмы работы со встроенными объектами ZIP и XML. Вы можете использовать готовые открытые библиотеки или встроенные средства 1С для программного формирования документов Word без запуска тяжелого стороннего приложения WINWORD.EXE. Это обеспечит колоссальный прирост производительности и абсолютную кроссплатформенность вашего решения.

← На главную