При разработке обработок для анализа файловой системы в среде 1С:Предприятие 7.7 программисты часто сталкиваются с проблемой прерывания выполнения кода. Типичная ситуация: ваша обработка сканирует дерево каталогов на системном диске и «спотыкается» на папках вроде Documents and Settings, System Volume Information или $RECYCLE.BIN. В современных версиях Windows (начиная с Windows 7) многие из этих путей являются не физическими папками, а точками соединения (Junction Points) или системными ссылками, доступ к которым ограничен даже для администратора. Если обращаться к ним напрямую через стандартные методы, программа выдает критическую ошибку и прекращает работу.
В этой статье мы подробно разберем, как грамотно построить алгоритм обхода папок, используя объект Scripting.FileSystemObject (FSO), и как сделать процесс устойчивым к ошибкам отсутствия прав доступа.
Проанализируем ситуацию: в ОС Windows 7 и выше папка C:\Documents and Settings физически отсутствует. Это «символическая ссылка» для совместимости со старым ПО, которая перенаправляет запросы в C:\Users. На уровне прав NTFS для таких ссылок часто установлен запрет на «Чтение списка содержимого». Когда объект FileSystemObject пытается получить коллекцию подпапок (SubFolders) или вычислить размер (Size) такой папки, возникает исключение COM-объекта, которое 1С 7.7 не может обработать без специальных инструкций.
Самый простой и эффективный способ в рамках 1С 7.7 — обернуть обращение к «опасным» свойствам объекта в конструкцию Попытка ... Исключение. Рассмотрим пример реализации обхода папок первого и второго уровня. Выясним, на каком этапе чаще всего происходят сбои.
Обычно ошибка возникает при попытке прочитать количество элементов в коллекции или при обращении к конкретному элементу. Разберем исправленный фрагмент кода:
// Перебор коллекции папок с обработкой ошибок
Для i = 0 по КолПапок - 1 Цикл
// Получаем объект папки через вспомогательную функцию VBScript
ы = глПолучитьЭлементКоллекцииПоНомеру(Коллекция1, i);
Попытка
// Проверка свойства Size или Name часто инициирует проверку прав доступа
// Если доступа нет, произойдет переход в блок Исключение
Если ПустоеЗначение(ы.Size) = 0 Тогда
ТЗ_Папки.НоваяСтрока();
ТЗ_Папки.ИмяПапки = ы.Name;
ТЗ_Папки.ТипФайла = ы.Type;
ТЗ_Папки.ПоложНаДиске = ы.Drive.Path;
ТЗ_Папки.РодительскаяПапка = ы.ParentFolder.Name;
ТЗ_Папки.ПолныйПуть = ы.Path;
ТЗ_Папки.ДатаСозданияПапки = ы.DateCreated;
ТЗ_Папки.ДатаПоследнегоДоступа = ы.DateLastAccessed;
ТЗ_Папки.ДатаПоследнегоИзменения = ы.DateLastModified;
ТЗ_Папки.Диск = БукваДиска;
ТЗ_Папки.ДлинаПути = СтрДлина(СокрЛП(ы.Path));
КонецЕсли;
Исключение
// Если папка защищена или является некорректной ссылкой,
// мы просто игнорируем её и продолжаем цикл
Сообщить("Нет доступа к объекту: " + ы.Path, "!");
КонецПопытки;
КонецЦикла;
Важный нюанс: Обратите внимание, что в 1С 7.7 коллекции COM-объектов не всегда позволяют использовать стандартный цикл Для Каждого (который появился только в 8-й версии). Поэтому мы используем вспомогательный объект MSScriptControl.ScriptControl для обращения к элементам коллекции по индексу через VBScript.
Иногда ошибка внутри COM-объекта настолько критична, что 1С 7.7 «вылетает» до того, как сработает код в блоке Исключение. В этом случае мы можем перенести логику обработки ошибок непосредственно внутрь скрипта, который передается в MSScriptControl. Рассмотрим, как прописать игнорирование ошибок в VBS-коде.
Добавим директиву On Error Resume Next. Это позволит скрипту не прерываться, если коллекция подпапок недоступна.
Функция глПолучитьКолВоЭлементовКоллекции(Коллекция)
ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
ScrptCtrl.Language = "vbscript";
ScrptCtrl.AddCode("
|Function GetCountCollection(ObjSet)
| On Error Resume Next
| Count = 0
| If Not (ObjSet Is Nothing) Then
| Count = ObjSet.Count
| End If
| If Err.Number <> 0 Then Count = 0
| GetCountCollection = Count
|End Function
|");
Возврат ScrptCtrl.Run("GetCountCollection", Коллекция);
КонецФункции
Использование On Error Resume Next гарантирует, что функция вернет 0 в случае проблем с правами, и основная программа на 1С продолжит выполнение без лишних диалоговых окон с ошибками.
Некоторые программисты предпочитают использовать встроенный объект 1С ФС. Методы НайтиПервыйФайл() и НайтиСледующийФайл() работают достаточно быстро, но имеют свои ограничения. Разберем их плюсы и минусы:
АтрибутыФайла(). Также встроенные методы 1С 7.7 иногда некорректно работают с длинными путями (более 255 символов) и специфическими кодировками.Проанализируем пример использования ФС для поиска:
ИмяФайла = "";
Каталог = "C:\";
Файл = ФС.НайтиПервыйФайл(Каталог + "*.*");
Пока ПустоеЗначение(Файл) = 0 Цикл
Если (Файл <> ".") И (Файл <> "..") Тогда
Атр = "";
ФС.АтрибутыФайла(Каталог + Файл, , Атр);
Если Сред(Атр, 4, 1) = "1" Тогда
// Это папка, обрабатываем её
КонецЕсли;
КонецЕсли;
Файл = ФС.НайтиСледующийФайл();
КонецЦикла;
Однако, как отмечают эксперты, методы ФС гарантированно работают только внутри каталога базы данных. При выходе «в дикую природу» системных дисков FileSystemObject оказывается гораздо мощнее и информативнее.
Если ваша задача — получить информацию о дисках и папках на системном уровне, рассмотрим использование WMI (Windows Management Instrumentation). Этот механизм позволяет делать запросы к операционной системе почти как к базе данных (WQL). Его главное преимущество — он часто позволяет прочитать метаданные о папке даже тогда, когда прямой доступ к её содержимому через проводник или FSO закрыт.
Пример получения списка логических дисков через WMI:
Локатор = СоздатьОбъект("WbemScripting.SWbemLocator");
Сервис = Локатор.ConnectServer(".");
Объекты = Сервис.ExecQuery("Select * from Win32_LogicalDisk Where DriveType = 3"); // Только жесткие диски
// Далее перебор коллекции Объекты
WMI работает медленнее, чем FSO, но он незаменим для системного администрирования и сбора информации о «проблемных» дисках.
Для создания действительно надежной обработки по сканированию файлов в 1С 7.7 придерживайтесь следующих правил:
Drive.IsReady. Обращение к пустому дисководу или картридеру вызовет длительное зависание системы.СписокЗначений), в который внесите $RECYCLE.BIN, System Volume Information и прочие служебные каталоги. Это сэкономит время и избавит от лишних срабатываний блока Исключение.ShortPath (формат 8.3), которое предоставляет FileSystemObject.Подведем итог: использование Scripting.FileSystemObject в связке с MSScriptControl и обязательной обработкой ошибок через Попытка — Исключение является «золотым стандартом» для работы с файловой системой в 1С 7.7. Это позволяет обходить системные ограничения современных ОС и создавать отказоустойчивые инструменты для работы с данными.