Jaime
Jaime

Reputation: 19

Install the same file to all subdirectories in Inno Setup

I am newbie with Inno Setup and I have been reading some threads but could not find how to do the following.

I simply would like to search for folders within a directory and in each folder detected install the same file with no selection of wizard page shown to the user. Not recursive, only files inside the detected folders and not subfolders.

I meant to install the same file in all folders detected while giving no option to the user to choose from. However, all other pages in the installer would be displayed as usual.

Thanks in advance

Upvotes: 2

Views: 231

Answers (2)

Martin Prikryl
Martin Prikryl

Reputation: 202088

Tag the file with dontcopy flag and then install it programmatically in CurStepChanged(ssInstall) (or ssPostInstall).

This will work well, only if the file is not huge. Otherwise the installer will unpleasantly hang. For a good user experience with huge files, more complex solution is needed.

#define TheFileName "thefile.txt"

[Files]
Source: "{#TheFileName}"; Flags: dontcopy

[Code]

procedure CurStepChanged(CurStep: TSetupStep);
var
  RootPath: string;
  TempPath: string;
  DestPath: string;
  FindRec: TFindRec;
  Count: Integer;
begin
  if CurStep = ssInstall then
  begin
    Log('Extracting {#TheFileName}...');
    ExtractTemporaryFile('{#TheFileName}');
    TempPath := ExpandConstant('{tmp}\{#TheFileName}');
    RootPath := ExpandConstant('{app}');
    Log(Format('Searching in "%s"...', [RootPath]));
    Count := 0;
    if not FindFirst(RootPath + '\*', FindRec) then
    begin
      Log(Format('"%s" not found.', [RootPath]));
    end
      else
    begin
      try
        repeat
          if (FindRec.Name <> '.') and (FindRec.Name <> '..') and
             (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0) then
          begin
            Log(Format('Found "%s".', [FindRec.Name]));
            DestPath := RootPath + '\' + FindRec.Name + '\{#TheFileName}';
            if FileCopy(TempPath, DestPath, False) then
            begin
              Log(Format('The file was installed to "%s".', [DestPath]));
              Inc(Count);
            end
              else
            begin
              Log(Format('Error installing the file to "%s".', [DestPath]));
            end;
          end;
        until not FindNext(FindRec);
      finally
        FindClose(FindRec);
      end;

      if Count = 0 then
      begin
        Log(Format('No subfolder to install file "%s" to was found in "%s".', [
          '{#TheFileName}', RootPath]));
      end
        else
      begin
        Log(Format('File "%s" was installed to %d subfolder(s) of "%s".', [
          '{#TheFileName}', Count, RootPath]));
      end;
    end;
  end;
end;

Alternatively, if you have a fixed set of folders, you can generate entry for each folder in the [Files] section using preprocessor:

[Files]
#define FolderEntry(Name) \
    "Source: ""C:\source\*""; DestDir: ""{app}\" + Name + """; " + \
         "Check: CheckDir('" + Name + "')"
#emit FolderEntry('2023')
#emit FolderEntry('2024')
#emit FolderEntry('2025')
[Code]
function CheckDir(DirName: string): Boolean;
begin
  Result := DirExists(ExpandConstant('{app}') + '\' + DirName);
end;

If you add SaveToFile to the end of the script:

#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")

... then you should see in Preprocessed.iss that the code generates a script like this:

[Files]
Source: "C:\source\*"; DestDir: "{app}\2023"; Check: CheckDir('2023')
Source: "C:\source\*"; DestDir: "{app}\2024"; Check: CheckDir('2024')
Source: "C:\source\*"; DestDir: "{app}\2025"; Check: CheckDir('2025')

Upvotes: 1

Jaime
Jaime

Reputation: 19

Thanks a lot Martin! I did it another way that may be of help to other users. I set a file for every potential folder I want to detect (it was only for four).

[Files] Source: "C:\Users\XXXXX\dll\*"; DestDir: "{commonappdata}\XXXX\2023"; Check:CheckDir2023;

Then I use the following to check if the folder exists:

function CheckDir2023 : Boolean;
   begin
     if (DirExists(ExpandConstant('{commonappdata}\xxxxxx\2023\'))) then
       begin
         Result := True;
       end
     else
     begin
       Result := False;
     end;
   end;

Upvotes: 0

Related Questions