Inno Setup получает размер каталога, включая подкаталоги

Я пытаюсь написать функцию, которая возвращает размер каталога. Я написал следующий код, но он не возвращает правильный размер. Например, когда я запускаю его на {pf} каталог возвращает 174 байта, что явно неверно, так как размер этого каталога составляет несколько гигабайт. Вот код, который у меня есть:

function GetDirSize(DirName: String): Int64;
var
  FindRec: TFindRec;
begin
  if FindFirst(DirName + '\*', FindRec) then
    begin
      try
        repeat
          Result := Result + (Int64(FindRec.SizeHigh) shl 32 + FindRec.SizeLow);
        until not FindNext(FindRec);
      finally
        FindClose(FindRec);
      end;
    end
  else
    begin
      Result := -1;
    end;
end;

Я подозреваю, что FindFirst Функция не включает подкаталоги, поэтому я не получаю правильный результат. Следовательно, как я могу вернуть правильный размер каталога, то есть включая все файлы во всех подкаталогах, так же, как при выборе Свойства для папки в проводнике Windows? я использую FindFirst так как функция должна поддерживать размеры каталогов более 2 ГБ.

1 ответ

Решение

FindFirst включает в себя подкаталоги, но вы не получите их размеры.

Вы должны перейти в подкаталоги и рассчитать общий размер файла за файлом, аналогично, например, Inno Setup: скопировать папку, подпапки и файлы рекурсивно в разделе кода.

function GetDirSize(Path: String): Int64;
var
  FindRec: TFindRec;
  FilePath: string;
  Size: Int64;
begin
  if FindFirst(Path + '\*', FindRec) then
  begin
    Result := 0;
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          FilePath := Path + '\' + FindRec.Name;
          if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
          begin
            Size := GetDirSize(FilePath);
          end
            else
          begin
            Size := Int64(FindRec.SizeHigh) shl 32 + FindRec.SizeLow;
          end;
          Result := Result + Size;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [Path]));
    Result := -1;
  end;
end;

За Int64вам нужна версия Inno Setup для Unicode, которую вы должны использовать в любом случае. Только если у вас есть очень веская причина придерживаться версии Ansi, вы можете заменить Int64 с Integer, но чем вы ограничены 2 ГБ.

Другие вопросы по тегам