|
v7: 1с77.FSO.Нет доступа к папке. Как продолжить выполнение обработки без прерывния по ошибке? | ☑ | ||
---|---|---|---|---|
0
Lsr1
08.06.22
✎
12:56
|
Задача: найти все ДИСКИ и информацию о них, Папки на каждом диске.
Windows 7, 1с7.7 27движок. Когда начинается обход подпапок папки Documents and Settings на системном диске, обработка прерывается с сообщением об ошибке. Папка1уровня=D:\Documents and Settings Folder=OLE.IFolder= КолПапок=Folder.SubFolders.Count; {G:\___БАЗЫ\.....\ЗАГОТОВКИ_ШАБЛОН.ERT(315)}: : Поскольку ОС Windows 7 физически папки Documents and Settings нет. Есть такая ссылка. Есть папка Users. Конечно, я могу мсключить определённые папки из сканирования (что сделано в коде), но хотелось бы знать, как грамотно решить проблему, когда не знаешь заранее о какую папку/файл споткнёшься (нет доступа к папке или файлу) . Вот весь код. //================================================== // Функция возвращает элемент коллекции по номеру //Функция глПолучитьЭлементКоллекцииПоНомеру(Коллекция,Номер) Экспорт Функция глПолучитьЭлементКоллекцииПоНомеру(Коллекция,Номер) //элементы(Items) ScrptCtrl=СоздатьОбъект("MSScriptControl.ScriptControl"); ScrptCtrl.Language="vbscript"; ScrptCtrl.AddCode(" |Function EnumerateCollection(ObjSet,Number) | Count = 0 | For Each Obj In ObjSet | If Count = Number Then | Set EnumerateCollection = Obj | Exit Function | End If | Count = Count + 1 | Next |End Function |"); Возврат ScrptCtrl.Run("EnumerateCollection",Коллекция,Номер); КонецФункции // глПолучитьЭлементКоллекцииПоНомеру //================================================== // Функция возвращает количество элементов коллекции // т.к. не каждый класс имеет свойство Count. Если оно // отсутствует, то для определения количества элементов // в коллекции применяется эта функция Функция глПолучитьКолВоЭлементовКоллекции(Коллекция) ScrptCtrl=СоздатьОбъект("MSScriptControl.ScriptControl"); ScrptCtrl.Language="vbscript"; ScrptCtrl.AddCode(" |Function GetCountCollection(ObjSet) | Count = 0 | For Each Obj In ObjSet | Count = Count + 1 | Next | GetCountCollection = Count |End Function |"); Возврат ScrptCtrl.Run("GetCountCollection",Коллекция); КонецФункции // глПолучитьКолВоЭлементовКоллекции //================================================== // Функция возвращает СОМОбъект по моникеру или имени файла // Фактически заменяет функцию ПолучитьCOMОбъект в версии 1С 8.х Функция глПолучитьCOMОбъект(СтрокаПараметров) ScrptCtrl=СоздатьОбъект("MSScriptControl.ScriptControl"); ScrptCtrl.Language="vbscript"; ScrptCtrl.AddCode(" |Function GetCOMObject(Str) | Set GetCOMObject = GetObject(Str) |End Function |"); Возврат ScrptCtrl.Run("GetCOMObject",СтрокаПараметров); КонецФункции // глПолучитьCOMОбъект //================================================== Процедура Сформировать() сообщить("32 найти все ДИСКИ и информацию о них, Папки на каждом диске. КОЛЛЕКЦИИ (Scripting.FileSystemObject) "); ЧасСтарта=""; МинСтарта=""; СекСтарта=""; ТекущееВремя(ЧасСтарта,МинСтарта,СекСтарта); FSO = CreateObject("Scripting.FileSystemObject"); //Для размещения информации о дисках ТЗ_Диски=СоздатьОбъект("ТаблицаЗначений"); ТЗ_Диски.НоваяКолонка("Буква",,,,,6,,); ТЗ_Диски.НоваяКолонка("Метка",,,,,16,,); ТЗ_Диски.НоваяКолонка("Тип",,,,,6,,); ТЗ_Диски.НоваяКолонка("СерНомер",,,,,20,,); ТЗ_Диски.НоваяКолонка("Объем",,,,,20,,); ТЗ_Диски.НоваяКолонка("Свободно",,,,,20,,); ТЗ_Диски.НоваяКолонка("ФайловаяСист",,,,,10,,); //Для размещения информации о папках 1-го уровня ТЗ_Папки=СоздатьОбъект("ТаблицаЗначений"); ТЗ_Папки.НоваяКолонка("ИмяПапки",,,,,30,,); ТЗ_Папки.НоваяКолонка("ТипФайла",,,,,10,,); //ТЗ_Папки.НоваяКолонка("Корень",,,,,20,,); ТЗ_Папки.НоваяКолонка("ПоложНаДиске",,,,,30,,); ТЗ_Папки.НоваяКолонка("РодительскаяПапка",,,,,30,,); ТЗ_Папки.НоваяКолонка("ПолныйПуть",,,,,20,,); //ТЗ_Папки.НоваяКолонка("РазмерПапки",,,,,20,,); ТЗ_Папки.НоваяКолонка("ДатаСозданияПапки",,,,,20,,); ТЗ_Папки.НоваяКолонка("ДатаПоследнегоДоступа",,,,,20,,); ТЗ_Папки.НоваяКолонка("ДатаПоследнегоИзменения",,,,,20,,); ТЗ_Папки.НоваяКолонка("Диск",,,,,10,,); ТЗ_Папки.НоваяКолонка("ДлинаПути",,,,,10,,); //Для размещения информации о папках 2-го уровня ТЗ_Папки2=СоздатьОбъект("ТаблицаЗначений"); ТЗ_Папки2.НоваяКолонка("ИмяПапки",,,,,30,,); ТЗ_Папки2.НоваяКолонка("ТипФайла",,,,,10,,); //ТЗ_Папки2.НоваяКолонка("Корень",,,,,20,,); ТЗ_Папки2.НоваяКолонка("ПоложНаДиске",,,,,30,,); ТЗ_Папки2.НоваяКолонка("РодительскаяПапка",,,,,30,,); ТЗ_Папки2.НоваяКолонка("ПолныйПуть",,,,,20,,); //ТЗ_Папки2.НоваяКолонка("РазмерПапки",,,,,20,,); ТЗ_Папки2.НоваяКолонка("ДатаСозданияПапки",,,,,20,,); ТЗ_Папки2.НоваяКолонка("ДатаПоследнегоДоступа",,,,,20,,); ТЗ_Папки2.НоваяКолонка("ДатаПоследнегоИзменения",,,,,20,,); //ТЗ_Папки2.НоваяКолонка("Диск",,,,,10,,); ТЗ_Папки2.НоваяКолонка("ДлинаПути",,,,,10,,); СЗ_ПапкаДляПоиска=СоздатьОбъект("СписокЗначений"); СЗ_ПапкаДляПоиска.ДобавитьЗначение("Install"); СЗ_ПапкаДляПоиска.ДобавитьЗначение("_Install"); //СЗ_ПапкаДляПоиска.ДобавитьЗначение("D:\Install"); //СЗ_ПапкаДляПоиска.ДобавитьЗначение("D:\_Install"); //Получить все диски, подключенные в системе Для A = 67 По 90 Цикл //по латинским буквам A- Z Если fso.DriveExists(Симв(A)) = -1 Тогда Drive = fso.GetDrive(Симв(A)); //СЗ_Диски=СоздатьОбъект ("СписокЗначений"); Если Drive.IsReady = -1 Тогда // Диск.DriveType = 1 - Flash накопитель // Диск.DriveType = 2 - Локальный жесткий диск // Диск.DriveType = 3 - Сетевой диск // Диск.DriveType = 4 - CD/DVD дисковод БукваДиска=Drive.DriveLetter; МеткаДиска=сокрЛП(FSO.GetDrive(Симв(A)).VolumeName); ТипДиска=Drive.DriveType; СерНомерДиска=сокрЛП(FSO.GetDrive(Симв(A)).SerialNumber); AvailableSpaceНаДиске=Drive.AvailableSpace; FileSystemДиск=Drive.FileSystem; FreeSpaceДиск=Drive.FreeSpace; PathДиск=Drive.Path; RootFolder=Drive.RootFolder.Path; TotalSizeДиск=Drive.TotalSize; //Сообщить("*********************************************"); //сообщить ("Имеется диск="+БукваДиска); //Сообщить("SerialNumber диска="+Симв(A)+": ="+сокрЛП(FSO.GetDrive(Симв(A)).SerialNumber)); //Сообщить("Имя диска="+Симв(A)+": ="+сокрЛП(FSO.GetDrive(Симв(A)).VolumeName)); //Сообщить("AvailableSpaceНаДиске="+AvailableSpaceНаДиске); //Сообщить("FileSystemДиск="+FileSystemДиск); //Сообщить("FreeSpaceДиск="+FreeSpaceДиск); //Сообщить("PathДиск="+PathДиск); //Сообщить("RootFolder="+RootFolder); ////"Ч16.0.,"-преобразовать число в строку длиной 16 символов, 0-без дробной части, разделитель триад -запятая //Сообщить("TotalSizeДиск="+формат(TotalSizeДиск,"Ч16.0.,")); //Если ТипДиска = 3 Тогда // если это сетевой диск, то укажем сетевой путь // Стр ="Сетевое имя=" + Drive.ShareName; // Сообщить(Стр); //КонецЕсли; //Сообщить("тип диска="+Симв(A)+": ="+ТипДиска); ТЗ_Диски.НоваяСтрока(); ТЗ_Диски.Буква=БукваДиска; ТЗ_Диски.Метка=МеткаДиска; ТЗ_Диски.Тип=ТипДиска; ТЗ_Диски.СерНомер=СерНомерДиска; ТЗ_Диски.Объем=формат(TotalSizeДиск,"Ч16.0.,"); ТЗ_Диски.Свободно=формат(FreeSpaceДиск,"Ч16.0.,"); ТЗ_Диски.ФайловаяСист=FileSystemДиск; //глФРМ(ЧислЗнач, Валюта="", ВыводНулевого=0, РаздТриад="'") КонецЕсли; КонецЕсли; КонецЦикла; Сообщить("Найдено дисков="+ТЗ_Диски.КоличествоСтрок()); //ТЗ_Диски.ВыбратьСтроку(,"Имеются диски. посмотри и закрой",); //Перебираю буквы дисков, что бы получить коллекцию папок ТЗ_Диски.ВыбратьСтроки(); //не искать на съемных дисках //Для ю=1 по ТЗ_Диски.КоличествоСтрок() Цикл Пока ТЗ_Диски.ПолучитьСтроку()=1 Цикл БукваДиска=СокрЛП(ТЗ_Диски.Буква); Если (ТЗ_Диски.Тип=1) или (ТЗ_Диски.Тип=3) или (ТЗ_Диски.Тип=4) Тогда //Сообщить("Тип=1 или 3 или 4. Следующий диск "); Продолжить;//следующий диск Иначе //HDD, ищем Folder = FSO.GetFolder(БукваДиска+":\");//Поиск папок Только в корне диска Коллекция1=Folder.SubFolders; //MsgBox Folder.SubFolders.Count КолПапок=Folder.SubFolders.Count; //Сообщить("Folder.SubFolders.Count ="+Folder.SubFolders.Count); //SubFolder1 = Folder.SubFolders.Item("Windows");//элемент=Item Обязательно существующая папка! иначе ругательство //MsgBox SubFolder.Path //Сообщить("Folder.SubFolders.Item(Windows).Path ="+SubFolder1.Path); //SubFolder2 = Folder.SubFolders("Windows"); //Обязательно существующая папка! иначе ругательство //MsgBox SubFolder.Path //Сообщить("Folder.SubFolders(Windows).Path ="+SubFolder2.Path); Для i=0 по КолПапок-1 Цикл ы=глПолучитьЭлементКоллекцииПоНомеру(Коллекция1,i); //Сообщить("ы="+ы);//ы=OLE.IFolder //Сообщить("ИмяРеальнойПодпапки="+ы.Name);// //Сообщить("*********************************************"); //Сообщить("Имя папки="+ы.Name); //Сообщить("Тип файла="+ы.Type); //Сообщить("Папка="+?(ы.IsRootFolder=-1,"корневая","не корневая")); //Сообщить("Расположена на диске="+ы.Drive.Path); //Сообщить("Родительская папка="+ы.ParentFolder.Name); //Сообщить("Полный путь до папки="+ы.Path); //Сообщить("Короткое имя папки="+ы.ShortName); //Сообщить("Короткий путь до папки="+ы.ShortPath); //Сообщить("Размер папки="+Формат(ы.Size,"Ч( )15.2")+" байт"); //Сообщить("Дата создания папки="+ы.DateCreated); //Сообщить("Дата последнего доступа к папке="+ы.DateLastAccessed); //Сообщить("Дата последнего изменения папки="+ы.DateLastModified); ТЗ_Папки.НоваяСтрока(); ТЗ_Папки.ИмяПапки=ы.Name; ТЗ_Папки.ТипФайла=ы.Type; //ТЗ_Папки.Корень=?(ы.IsRootFolder=-1,"корневая","не корневая"); ТЗ_Папки.ПоложНаДиске=ы.Drive.Path; ТЗ_Папки.РодительскаяПапка=ы.ParentFolder.Name; ТЗ_Папки.ПолныйПуть=ы.Path; //ТЗ_Папки.РазмерПапки=0; ТЗ_Папки.ДатаСозданияПапки=ы.DateCreated; ТЗ_Папки.ДатаПоследнегоДоступа=ы.DateLastAccessed; ТЗ_Папки.ДатаПоследнегоИзменения=ы.DateLastModified; ТЗ_Папки.Диск=БукваДиска; ТЗ_Папки.ДлинаПути=СтрДлина(СокрЛП(ы.Path)); КонецЦикла; КонецЕсли; //Сообщить("Кол-во папок в корне диска="+БукваДиска+" ="+КолПапок); КонецЦикла ; //Сообщить("Всего коренных папок на всех логических HDD найдено="+ТЗ_Папки.КоличествоСтрок()); //ТЗ_Папки.ВыбратьСтроку(,"Имеются коренные папки. посмотри и закрой",); //Теперь можно найти папки 2-го уровня КолНеСканПапок=0; ТЗ_Папки.ВыбратьСтроки(); Пока ТЗ_Папки.ПолучитьСтроку()=1 Цикл НеСканировать= СокрЛП(ТЗ_Папки.ИмяПапки); //Если (НеСканировать = "Documents and Settings") или (НеСканировать = "System Volume Information") //или (НеСканировать = "Recycled") или (НеСканировать = "$RECYCLE.BIN") Тогда // КолНеСканПапок=КолНеСканПапок+1; // Продолжить;//пропустить сканирование подпапок этой папки //КонецЕсли; Папка1уровня=ТЗ_Папки.ПолныйПуть; Сообщить("Папка1уровня="+Папка1уровня); Folder = FSO.GetFolder(Папка1уровня);//+"\" Поиск папок 2-го уровня Сообщить("Folder="+Folder+"="); //On Error Resume Next;//продолжить в случае ошибки Коллекция1=Folder.SubFolders; //MsgBox Folder.SubFolders.Count КолПапок=Folder.SubFolders.Count; Сообщить("Folder.SubFolders.Count ="+Folder.SubFolders.Count); //SubFolder1 = Folder.SubFolders.Item("Windows");//элемент=Item Обязательно существующая папка! иначе ругательство //MsgBox SubFolder.Path //Сообщить("Folder.SubFolders.Item(Windows).Path ="+SubFolder1.Path); //SubFolder2 = Folder.SubFolders("Windows"); //Обязательно существующая папка! иначе ругательство //MsgBox SubFolder.Path //Сообщить("Folder.SubFolders(Windows).Path ="+SubFolder2.Path); Для i=0 по КолПапок-1 Цикл ы=глПолучитьЭлементКоллекцииПоНомеру(Коллекция1,i); ТЗ_Папки2.НоваяСтрока(); ТЗ_Папки2.ИмяПапки=ы.Name; ТЗ_Папки2.ТипФайла=ы.Type; //ТЗ_Папки.Корень=?(ы.IsRootFolder=-1,"корневая","не корневая"); ТЗ_Папки2.ПоложНаДиске=ы.Drive.Path; ТЗ_Папки2.РодительскаяПапка=ы.ParentFolder.Name; ТЗ_Папки2.ПолныйПуть=ы.Path; //ТЗ_Папки.РазмерПапки=0; ТЗ_Папки2.ДатаСозданияПапки=ы.DateCreated; ТЗ_Папки2.ДатаПоследнегоДоступа=ы.DateLastAccessed; ТЗ_Папки2.ДатаПоследнегоИзменения=ы.DateLastModified; ТЗ_Папки2.ДлинаПути=СтрДлина(СокрЛП(ы.Path)); //ТЗ_Папки.Диск=БукваДиска; КонецЦикла; КонецЦикла; //КонецЕсли; Сообщить("2-го уровня на всех логических HDD просканировано="+ТЗ_Папки2.КоличествоСтрок()+", исключены из анализа="+КолНеСканПапок+" папок 1-го уровня", ); ЧасФиниш=""; МинФиниш=""; СекФиниш=""; ТекущееВремя(ЧасФиниш,МинФиниш,СекФиниш); Сообщить("Время старта="+ЧасСтарта+":"+МинСтарта+":"+СекСтарта+" Время финиша="+ЧасФиниш+":"+МинФиниш+":"+СекФиниш); ТЗ_Папки2.ВыбратьСтроку(,"Имеются папки. посмотри и закрой",); КонецПроцедуры |
|||
1
mikecool
08.06.22
✎
13:00
|
Попытка - Исключение
|
|||
2
АгентБезопасной Нацио
08.06.22
✎
13:17
|
а что, штатные НайтиПервыйФайл()/НайтиСледующийФайл()/АтрибутыФайла() - отменили?
|
|||
3
Lsr1
08.06.22
✎
13:35
|
Блин, и на старуху бывает проруха. про слона то я и забыл.
(1) СПАСИБО! (2) Нет, не отменили, но у штатной файловой системы 1С7.7, на сколько я помню, есть весьма серьезные ограничения. Вот часть, которую исправил. Для i=0 по КолПапок-1 Цикл ы=глПолучитьЭлементКоллекцииПоНомеру(Коллекция1,i); Попытка Если ПустоеЗначение(ы.Size)=0 Тогда ТЗ_Папки.НоваяСтрока(); ТЗ_Папки.ИмяПапки=ы.Name; ТЗ_Папки.ТипФайла=ы.Type; //ТЗ_Папки.Корень=?(ы.IsRootFolder=-1,"корневая","не корневая"); ТЗ_Папки.ПоложНаДиске=ы.Drive.Path; ТЗ_Папки.РодительскаяПапка=ы.ParentFolder.Name; ТЗ_Папки.ПолныйПуть=ы.Path; //ТЗ_Папки.РазмерПапки=0; ТЗ_Папки.ДатаСозданияПапки=ы.DateCreated; ТЗ_Папки.ДатаПоследнегоДоступа=ы.DateLastAccessed; ТЗ_Папки.ДатаПоследнегоИзменения=ы.DateLastModified; ТЗ_Папки.Диск=БукваДиска; ТЗ_Папки.ДлинаПути=СтрДлина(СокрЛП(ы.Path)); КонецЕсли; Исключение //Сообщить(ОписаниеОшибки()); КонецПопытки; КонецЦикла; |
|||
4
Lsr1
08.06.22
✎
15:54
|
(2) Нашёл здесь :_https://newexp.ru/public/21208/
Методы ФС ГАРАНТИРОВАНО (прошу прощения за каплок, но иного способа выделения здесь не знаю) работают только внутри каталога рабочей базы. Потомушто каталог базы в полном доступе. Так надо :)) А вот вне БД встречаются места, не обремененные полным доступом для вас, как юзера... Вы, конечно, можете написать ФС.КопироватьФайл(бла-бла-бла), только вот этот метод ничегошеньки не сообщит, если копирование не произойдет. И причину не сообщит. И даже не смотрите в сторону Попытка...Исключение: прерывания оси 1С не видит... Потому рекомендую пользовать FileSystemObject из Windows Script Host... Это все-таки компонента, "встроенная" в ось, потому работать будет с бОльшей гарантией, чем любая ВК и даже 1С ;) И побогаче будет. И отрабатывает прерывания исполнения... |
|||
5
MWWRuza
гуру
09.06.22
✎
21:37
|
(4) Вы, конечно, можете написать ФС.КопироватьФайл(бла-бла-бла), только вот этот метод ничегошеньки не сообщит, если копирование не произойдет. И причину не сообщит. И даже не смотрите в сторону Попытка...Исключение: прерывания оси 1С не видит...
Ну, или, вариант, проверять наличие файла в целевом каталоге после копирования... Типо так, фрагмент из рабочей конфы, выгрузка файлов из бэк 1С во фронты(кассы): Процедура ЗаписатьФайл(КаталогОбмена, ИмяФайлаВыгрузкиCCRS_POS, мИмяФайла) ИмяФайлаВыгрузки = КаталогОбмена + ?(Прав(КаталогОбмена, 1) <> "\", "\", "") + "inp\" + мИмяФайла; Если ФС.СуществуетФайл(ИмяФайлаВыгрузкиCCRS_POS)=1 Тогда ФС.КопироватьФайл(ИмяФайлаВыгрузкиCCRS_POS,ИмяФайлаВыгрузки,0); Если ФС.СуществуетФайл(ИмяФайлаВыгрузки)=1 Тогда Сообщить ("Выгружен "+ ИмяФайлаВыгрузки); Иначе Сообщить ("Не удалось создать файл "+ ИмяФайлаВыгрузки); КонецЕсли; КонецЕсли; КонецПроцедуры //ЗаписатьФайл |
|||
6
Злопчинский
10.06.22
✎
00:13
|
(5) пичалька будет в том что если ИмяФайлаВыгрузки по месту назначения уже существует, но у кеода нет прав доступа, то этот код соврет... Поэтому сначала проверяем наличие файла по месту назначения, удаляем файл по месту назначения, проверяем на отсутствие файла и только потом копируем. И даже такой сценарий содержит дырки если права на удалением создание разные (точно не помню, могу тут лажать). Но описанный подход лучше чем код в пред.посте
|
|||
7
MWWRuza
гуру
10.06.22
✎
08:55
|
(6) Здесь, я с тобой полностью согласен... Просто писать чего-то ради демонстрации, было лень. Выдрал из рабочей конфы рабочий кусок. А там, такой ситуации быть просто не может, по определению - файлы удаляются фронтом автоматически, при загрузке товара в кассовую программу. И даже, если предположить, что по каким-то причинам этого не произошло - ну, например кассовая программа не запущена, то все равно не этого не произойдет - там имена файлов(мИмяФайла) каждую выгрузку уникальны(к стандартному имени файла, добавляется число секунд с начала года, и кассовая программа грузит файлы "по маске" - "ИмяНужногоФайла*.xml"). Сделано так для того, что если в файл закралась ошибка, то касовая программа не просто удаляет файл после загрузки всего, что смогла, а перемещает его в подпапку "EROR" в папке загрузки, для дальнейшего анализа и исправления ошибок в базе, и в таком случае, файлы не перезаписываются, т.к. имена у них уникальные.
А в общем случае, да, при использовании такого алгоритма, надо проверять наличие файла перед копированием. А с правами на создание/удаление... Я как-то не заморачивался. Тут не скажу. |
|||
8
uno-group
10.06.22
✎
11:57
|
Обычно из 1с не нужно работать с файлами валяющимися где попало с какими попало правами доступа. ИМХО это задача админа раздать нормально права на папки и файлы.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |