В процессе разработки на платформе 1С:Предприятие часто возникает задача управления файловой системой, в частности — перемещение целых папок с их содержимым. Несмотря на наличие встроенных функций, разработчики часто сталкиваются с ошибками вроде «Неправильный путь к файлу. Объект является каталогом» или системными исключениями COM-объектов. В этой статье мы подробно разберем, как правильно реализовать перемещение каталогов, проанализируем ошибки автора темы и рассмотрим альтернативные, более надежные способы решения задачи.
Начнем с того, почему стандартный метод 1С ПереместитьФайл может выдавать ошибку. Рассмотрим типичный вызов:
ПереместитьФайл(СтараяПолнаяПапкаФайловПроекта, НоваяПолнаяПапкаФайловПроекта);
Проанализируем ситуацию: если платформа сообщает, что «Объект является каталогом», это часто означает, что метод ожидает маску файла или работает в контексте, который не поддерживает автоматическое создание дерева каталогов в данной версии или конфигурации прав. Однако важно помнить: в актуальных версиях 1С 8.3 метод ПереместитьФайл должен уметь перемещать каталоги, но при одном критическом условии — папка-приемник не должна существовать. Если целевой каталог уже создан, операционная система или платформа могут заблокировать операцию переименования/перемещения дескриптора папки.
Когда встроенные средства не справляются, программисты часто прибегают к использованию Windows-компоненты Scripting.FileSystemObject. Это мощный инструмент, но он требует аккуратности в синтаксисе путей. Разберем код, предложенный в обсуждении:
Процедура ПереместитьКаталогFSO(Источник, Приемник) Экспорт
// Источник и приемник должны быть без финальных слешей
FSO = Новый COMОбъект("Scripting.FileSystemObject");
// Проверяем наличие исходной папки
Если Не FSO.FolderExists(Источник) Тогда
Возврат;
КонецЕсли;
// Вариант 1: Прямое перемещение (может вызвать ошибку 0x800a004c)
// FSO.MoveFolder(Источник, Приемник);
// Вариант 2: Поэлементное перемещение
Файлы = НайтиФайлы(Источник, "*.*", Ложь);
СоздатьКаталог(Приемник);
Для Каждого Файл ИЗ Файлы Цикл
Попытка
FSO.MoveFolder(Файл.ПолноеИмя, Приемник + "\" + Файл.Имя);
Исключение
// Обработка одиночных файлов, если Файл не является папкой
FSO.MoveFile(Файл.ПолноеИмя, Приемник + "\" + Файл.Имя);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Выясним причину ошибки 0x800a004c (Path not found). Она часто возникает, если в пути используются некорректные символы или, что бывает чаще, если метод MoveFolder пытается переместить папку между разными логическими дисками (например, с диска C: на диск D:). В архитектуре Windows прямое перемещение (move) — это смена указателя в таблице файловой системы. Между разными дисками это невозможно, поэтому требуется сначала копирование, а затем удаление.
Если задача стоит не в распределении файлов по разным веткам, а в простом переносе папки внутри одного родительского каталога (или на том же диске), эффективнее использовать метод переименования. Рассмотрим пример кода:
objFSO = Новый COMОбъект("Scripting.FileSystemObject");
objFolder = objFSO.GetFolder("D:\Проекты\СтароеИмя");
objFolder.Name = "НовоеИмя";
Это самый быстрый способ, так как он не требует физического копирования данных байт за байтом. Однако он не сработает, если НовоеИмя подразумевает перемещение в другую вложенную структуру, которой еще не существует.
Для более «умного» перемещения, которое ведет себя аналогично проводнику Windows (автоматически объединяет папки, обрабатывает конфликты имен), можно использовать объект Shell.Application. Посмотрим на пример реализации:
Shell = Новый COMОбъект("Shell.Application");
ПапкаПриемник = Shell.NameSpace("D:\ЦелевойКаталог");
Если ПапкаПриемник <> Неопределено Тогда
ПапкаПриемник.MoveHere("D:\ИсходныйКаталог");
КонецЕсли;
Метод MoveHere хорош тем, что он более толерантен к различным дискам и правам доступа, чем «голый» FSO.
Проанализируем важные нюансы, которые помогут избежать зависаний и ошибок доступа:
USR1CV8 (или того, под которым запущен агент сервера) есть полные права на чтение, запись и удаление в обеих папках.ЗаписьТекста или ЧтениеДанных). Если объект не был явно закрыт (установлен в Неопределено), папка будет заблокирована операционной системой.ФайловаяСистема.ПереместитьФайл. Разработчики БСП уже внедрили туда все необходимые проверки на существование путей и корректную обработку ошибок.Robocopy через команду ЗапуститьПриложение:
Команда = "robocopy ""D:\Source"" ""D:\Dest"" /E /MOVE /R:3 /W:5";
ЗапуститьПриложение(Команда,, Истина);
Параметр /E копирует все подпапки (включая пустые), а /MOVE удаляет их из источника после успешного переноса. Это наиболее надежный способ для работы с промышленными объемами данных.
Подводя итог, можно сказать: для простых задач достаточно встроенного ПереместитьФайл при условии отсутствия целевой папки. Для сложных структур на Windows-серверах лучше всего подходит Robocopy или Shell.Application, так как они наиболее корректно обрабатывают специфику файловой системы.