Как правильно скопировать и заархивировать каталог в 1С

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

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

Почему не работает вызов системных команд с перенаправлением вывода

Рассмотрим распространенную ошибку при попытке выполнить команду через метод КомандаСистемы. Если в параметрах используется оператор перенаправления вывода > или >>, а в качестве приемника указан путь к папке, операционная система вернет ошибку отказа в доступе. Символ > ожидает обязательного указания полного имени целевого файла, например C:\Temp\log.txt, а не пути к директории C:\Temp\.

Кроме того, операторы перенаправления вывода и конвейеры (|) обрабатываются исключительно командным интерпретатором Windows. Если запускать утилиту напрямую, перенаправление не сработает. Чтобы выполнить команду корректно, необходимо передавать ее через командную оболочку cmd.exe с ключом /c, а все пути, содержащие пробелы, экранировать кавычками.

Способ 1. Штатная архивация каталога через объект ЗаписьZipФайла

Для архивации файлов платформы 1С предоставляет встроенный объект ЗаписьZipФайла. Частая ошибка разработчиков заключается в передаче в метод Добавить() простого пути к каталогу. В этом случае платформа добавляет в архив только саму пустую директорию, игнорируя ее содержимое.

Чтобы заархивировать всю структуру папки с вложенными файлами и подкаталогами, необходимо добавить к пути маску \* и явно передать параметры рекурсивной обработки:


// Создание ZIP-архива каталога
ИмяФайлаАрхива = "C:\Backup\Archive.zip";
КаталогИсточник = "C:\Data";

Архиватор = Новый ЗаписьZipФайла(ИмяФайлаАрхива, , , МетодСжатияZIP.Сжатие, УровеньСжатияZIP.Максимальный);

// Добавляем все файлы и подкаталоги с сохранением путей
МаскаФайлов = КаталогИсточник + "\*";
Архиватор.Добавить(МаскаФайлов, РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);

Попытка
    Архиватор.Записать();
Исключение
    Архиватор = Неопределено;
    ВызватьИсключение "Ошибка при создании архива: " + ОписаниеОшибки();
КонецПопытки;

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

Способ 2. Копирование каталогов системными утилитами Windows

Если перед архивацией или переносом требуется скопировать директорию на диске средствами операционной системы, рассмотрим два основных инструмента командной строки: xcopy и robocopy.

  1. Использование утилиты xcopy: для корректного переноса вложенных директорий и предотвращения интерактивных вопросов о подтверждении перезаписи требуются ключи /E (включая пустые папки), /I (считать приемник папкой) и /Y (подавлять запрос подтверждения).
  2. Использование утилиты robocopy: более надежный инструмент для Windows, корректно работающий с длинными путями, сетевыми ресурсами и атрибутами файлов.

Посмотрим на пример вызова системных команд через метод ЗапуститьПриложение с перенаправлением вывода в лог-файл:


КаталогОткуда = "C:\SourceFolder";
КаталогКуда   = "D:\DestinationFolder";
ФайлЛога      = "C:\Logs\copy_log.txt";

// Формируем команду для cmd.exe с утилитой robocopy
СтрокаКоманды = СтрШаблон("cmd.exe /c robocopy ""%1"" ""%2"" /E /R:3 /W:5 > ""%3""", КаталогОткуда, КаталогКуда, ФайлЛога);

// Запуск с ожиданием завершения процесса
КодВозврата = 0;
ЗапуститьПриложение(СтрокаКоманды, , Истина, КодВозврата);

Если КодВозврата >= 8 Тогда
    // Для robocopy код возврата 8 и выше означает фатальную ошибку
    ВызватьИсключение "Ошибка при выполнении копирования. Код возврата: " + Строка(КодВозврата);
КонецЕсли;

Способ 3. Синхронное копирование каталога через COM-объект

В среде Windows в толстом клиенте или серверном контексте можно использовать объект операционной системы Scripting.FileSystemObject. Этот подход позволяет копировать папки синхронно без открытия окон командной строки:


КаталогОткуда = "C:\SourceFolder";
КаталогКуда   = "D:\DestinationFolder";

ФСО = Новый COMОбъект("Scripting.FileSystemObject");
Попытка
    // Третий параметр Истина разрешает перезапись существующих файлов
    ФСО.CopyFolder(КаталогОткуда, КаталогКуда, Истина);
Исключение
    ВызватьИсключение "Не удалось скопировать каталог через FileSystemObject: " + ОписаниеОшибки();
КонецПопытки;

Нюансы контекста исполнения и кроссплатформенности

При выборе способа копирования и архивации важно учитывать особенности серверной среды:

  1. Клиентский и серверный контекст: процедура КомандаСистемы доступна исключительно на клиенте. В серверных модулях, фоновых и регламентных заданиях необходимо использовать метод ЗапуститьПриложение.
  2. Права доступа службы: при запуске команд на стороне сервера процесс исполняется с правами системного пользователя, от имени которого работает служба 1С:Предприятия (например, usr1cv8). У этого пользователя должны быть выданы права на чтение исходной папки и запись в целевую директорию.
  3. Кроссплатформенность: утилиты xcopy, robocopy и COM-объекты работают только в Windows. Если сервер 1С работает под управлением Linux, рекомендуется использовать кроссплатформенный встроенный объект ЗаписьZipФайла либо вызывать системные утилиты cp -r и zip, предварительно определив операционную систему через свойство ИнформацияОбОС.
← На главную