开发者

How do I reliably determine folder size using FileSystemObject.Size?

开发者 https://www.devze.com 2023-02-28 12:26 出处:网络
Trying to compute the size of a folder that could be very large, I used FileSystemObject.Size: #! perl

Trying to compute the size of a folder that could be very large, I used 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;
}

For some cases, folder_size returns normally, but for others, the call to Size throws exceptions. Computing the sizes of folders in C:\ with

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 - $size\n";
}

I get the following output:

C:\$Recycle.Bin - Size C:\$Recycle.Bin: The resource loader failed to find MUI file at olesize line 22.
C:\boot - 17463020
C:\cygwin - 1835711453
C:\DELL - 133184282
C:\doctemp - 12811140
C:\Documents and Settings - Size C:\Documents and Settings: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Drivers - 180746384
C:\eclipse - 324690795
C:\EFI - 262144
C:\found.000 - Size C:\found.000: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\ghc - 1014658071
C:\gtk2hs - 138050118
C:\PerfLogs - Size C:\PerfLogs: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Perl - 115648300
C:\Program Files - Size C:\Program Files: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\ProgramData - Size C:\ProgramData: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Python25 - 83902423
C:\System Volume Information - Size C:\System Volume Information: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Users - Size C:\Users: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Virtual Machines - 5401825804
C:\Windows - Size C:\Windows: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\xampp - 408475320

It seems to be at least partially a permission issue because running the code as Administrator changes some of the output (noted in bold).

C:\$Recycle.Bin - 2062958143
C:\boot - 17463020
C:\cygwin - 1835711453
C:\DELL - 133184282
C:\doctemp - 12811140
C:\Documents and Settings - Size C:\Documents and Settings: The resource loader failed to find MUI file at olesize line 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 Files - 10857194364
C:\ProgramData - Size C:\ProgramData: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Python25 - 83902423
C:\System Volume Information - Size C:\System Volume Information: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Users - Size C:\Users: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\Virtual Machines - 5401825804
C:\Windows - Size C:\Windows: The resource loader cache doesn't have loaded MUI entry at olesize line 22.
C:\xampp - 408475320

The MUI error message corresponds to ERROR_MUI_FILE_NOT_FOUND.

How is my code incorrect?

For context, I have no requirement to use FileSystemObject. Other approaches I considered were scraping the output of dir /s and summing the sizes of all leaves in the subtree. For large directories, the output of dir /s could be enormous, and scouring an entire subtree is a performance dog. Windows Explorer always seems to be abl开发者_StackOverflow中文版e to compute the result given enough time, so is there a way to call whatever it's doing?


Another option is to stick to pure-perl: Filesys::DiskUsage does about the same thing. However, I'm betting that permission issues will remain. It should at least be better than scraping the output of dir /s.

To be honest, if Explorer works on these directories when you're not logged in as administrator, that seems like a privilege escalation issue in Explorer to me - apparently, Explorer can access the filesystem as if it were the administrator even when it isn't logged in as such, so if you can get your own DLL loaded by Explorer, you, too, could have admin access.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号