Reputation: 19
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
Reputation: 202088
Tag the file with dontcopy
flag and then install it programmatically in CurStepChanged(ssInstall)
(or ssPostInstall
).
ExtractTemporaryFile
to extract the file to a temporary folder.FindFirst
/FindNext
functions to find the subfolders.CopyFile
to copy the file from a temporary folder to the found subfolder(s).Log
a lot.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
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