Как мне надежно определить размер папки с помощью FileSystemObject.Size?

#windows #perl #win32ole #windows-scripting #filesystemobject

#Windows #perl #win32ole #windows-скриптинг #filesystemobject

Вопрос:

Пытаясь вычислить размер папки, который мог бы быть очень большим, я использовал FileSystemObject.Size :

 #! perl

use strict;
use warnings;

use 5.10.0;

use File::Spec;
use Win32::OLE;

my $_fso;
sub folder_size {
  my($folder) = @_;

  $_fso = Win32::OLE->new("Scripting.FileSystemObject")
    unless defined $_fso;

  die "GetFolder $folder: $^E"
    unless defined(my $f = $_fso->GetFolder($folder));

  my $size = $f->Size;
  die "Size $folder: $^E" unless defined $size;

  $size;
}
  

В некоторых случаях folder_size возвращается нормально, но в других вызов Size вызывает исключения. Вычисление размеров папок в C: с

 my $root = "C:/";
opendir my $dh, $root or die "$0: opendir: $!";

while (defined(my $name = readdir $dh)) {
  next if $name eq "." || $name eq "..";
  my $folder = File::Spec->catdir($root, $name);
  next unless -d $folder;

  chomp(my $size = eval { folder_size $folder } // $@);
  print "$folder - $sizen";
}
  

Я получаю следующий вывод:

C: $Recycle.Размер ячейки C:  $ Recycle.Bin: загрузчику ресурсов не удалось найти MUI-файл в строке 22 olesize.
C:boot - 17463020
C:cygwin - 1835711453
C:DELL - 133184282
C:doctemp - 12811140
C:Documents и настройки - Размер C:Documents и настройки: в кэше загрузчика ресурсов нет записи loaded MUI в строке olesize 22.
C:Drivers - 180746384
C:eclipse - 324690795
C:EFI - 262144
C:found.000 - Размер C:found.000: В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:ghc - 1014658071
C:gtk2hs - 138050118
C:PerfLogs - Размер C:PerfLogs : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Perl - 115648300
C:Program Файлы - Размер C:Program Файлы: В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:ProgramData - Размер C:ProgramData : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Python25 - 83902423
C:System Информация о томе - Размер C:System Информация об объеме: в кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Users - Размер C:Users : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Virtual Компьютеры - 5401825804
C:Windows - Размер C:Windows : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:xampp - 408475320

Похоже, что это, по крайней мере частично, проблема с разрешениями, потому что запуск кода от имени администратора изменяет часть выходных данных (выделено жирным шрифтом).

C:$Recycle.Bin - 2062958143
C:boot - 17463020
C:cygwin - 1835711453
C:DELL - 133184282
C:doctemp - 12811140
C:Documents и настройки - Размер C:Documents и настройки: загрузчику ресурсов не удалось найти MUI-файл в строке olesize 22.
C:Drivers - 180746384
C:eclipse - 324690795
C:EFI - 262144
C:found.000 - 8950
C:ghc - 1014658071
C:gtk2hs - 138050118
C:PerfLogs - 0
C:Perl - 115648300
C:Program Файлы - 10857194364
C:ProgramData - Размер C:ProgramData : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Python25 - 83902423
C:System Информация о томе - Размер C:System Информация об объеме: в кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Users - Размер C:Users : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:Virtual Компьютеры - 5401825804
C:Windows - Размер C:Windows : В кэше загрузчика ресурсов нет записи loaded MUI в строке 22 olesize.
C:xampp - 408475320

Сообщение об ошибке MUI соответствует ERROR_MUI_FILE_NOT_FOUND .

Почему мой код неверен?

Что касается контекста, у меня нет никаких требований к использованию FileSystemObject . Другими подходами, которые я рассматривал, были очистка выходных данных dir /s и суммирование размеров всех листьев в поддереве. Для больших каталогов выходные данные dir /s могут быть огромными, а очистка всего поддерева — это контроль производительности. Кажется, что проводник Windows всегда может вычислить результат за достаточное время, так есть ли способ вызвать то, что он делает?

Комментарии:

1. Я подозреваю, что Explorer просто игнорирует исключения. Что произойдет, если вы попытаетесь измерить одну из папок, которая получает исключение, с помощью Explorer?

2. у @cjm Explorer нет никаких проблем с C:Program Files или C:Windows : размер в таблице свойств устанавливается при ответе в течение 30 секунд. Заполнение глубины каталогов с помощью File::Find занимает как минимум в 5 раз больше времени.

Ответ №1:

Другой вариант — придерживаться чистого perl: Filesys::DiskUsage делает примерно то же самое. Однако я готов поспорить, что проблемы с разрешениями останутся. Это должно быть, по крайней мере, лучше, чем очистка выходных данных dir /s .

Честно говоря, если Explorer работает с этими каталогами, когда вы не вошли в систему как администратор, мне кажется, что это проблема с повышением привилегий в Explorer — по-видимому, Explorer может получить доступ к файловой системе, как если бы он был администратором, даже когда он не вошел в систему как таковой, поэтому, если вы можете загрузить свою собственную DLL с помощью Explorer, вы тоже можете иметь доступ администратора.