Search code examples
inno-setuppascalscript

Copy folder, subfolders and files recursively in Inno Setup Code section


Is there any way to browse and recursively copy/move all files and subdirectories of a directory within the code section? (PrepareToInstall)

I need to ignore a specific directory, but using xcopy it ignores all directories /default/, for example, and I need to ignore a specific only.

The Files section is executed at a later time when needed.


Solution

  • To recursively copy a directory programmatically use:

    procedure DirectoryCopy(SourcePath, DestPath: string);
    var
      FindRec: TFindRec;
      SourceFilePath: string;
      DestFilePath: string;
    begin
      if FindFirst(SourcePath + '\*', FindRec) then
      begin
        try
          repeat
            if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
            begin
              SourceFilePath := SourcePath + '\' + FindRec.Name;
              DestFilePath := DestPath + '\' + FindRec.Name;
              if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
              begin
                if FileCopy(SourceFilePath, DestFilePath, False) then
                begin
                  Log(Format('Copied %s to %s', [SourceFilePath, DestFilePath]));
                end
                  else
                begin
                  Log(Format('Failed to copy %s to %s', [
                    SourceFilePath, DestFilePath]));
                end;
              end
                else
              begin
                if DirExists(DestFilePath) or CreateDir(DestFilePath) then
                begin
                  Log(Format('Created %s', [DestFilePath]));
                  DirectoryCopy(SourceFilePath, DestFilePath);
                end
                  else
                begin
                  Log(Format('Failed to create %s', [DestFilePath]));
                end;
              end;
            end;
          until not FindNext(FindRec);
        finally
          FindClose(FindRec);
        end;
      end
        else
      begin
        Log(Format('Failed to list %s', [SourcePath]));
      end;
    end;
    

    Add any filtering you need. See how the . and .. are filtered.


    Note that the function does not create the root DestPath. If you do not know if it exists, add this to be beginning of the code:

    if DirExists(DestPath) or CreateDir(DestPath) then
    

    (then the similar code before the recursive DirectoryCopy call becomes redundant)


    For an example of use, see my answers to questions: