Checking existence of a file in Inno Setup Internal Temporary folder - inno-setup

I want my Inno Setup Script to search for my setup's .TMP file which usually creates in currently logged user's Local Application Data folder and give user a message box saying "Your Setup's Temporary Source seems to be created successfully."
I wrote a code to do so:
if CurPageID = wpLicence then begin
if FileExists((ExpandConstant('{localappdata}\Temp\is-*****.tmp\MySetup.tmp'))) then begin
MsgBox('Your Setup''s Temporary Source seems to be created successfully.', mbInformation, MB_OK);
MsgBox('It is located in: <<I WANT TO GET THE FOUND FILE''S FULL PATH HERE>>', mbWarning, MB_OK);
end;
end;
But, even my setup's temporary file (MySetup.tmp) exists when the setup starts, I'm not getting those message boxes.
What is the problem in this code?
Is the is-***** ignored when searching?
UPDATED QUESTION
I mean The Temporary Directory shown in below image. It contains the internal Temporary File of the Setup Wizard. This is usually named like {#SetupName}.tmp...... Not the other Temporary Directory which Inno Setup extracts Files of the Setup. such as ISSKin.dll or any externally used files.
Any help would be greatly appreciated.

The FileExists function does not support wildcards, not even in a file name, let alone in a name of a parent folder.
See How to test using wildcards whether a file exists in Inno Setup.
Though in your case, just use the ParamStr(0).
FileExists(ParamStr(0))

Related

Inno Setup - How to copy the created setup file

I want to copy the created setup file to a network directory. I think the [Run] section will be the best position to do this, but I cannot not found any possibility to call my copy function. Any idea to this issue?
Also, is it possible to use variables declared in the [setup] section for the copy path?
My procedure will be like this (trying to use the variables):
[Code]
procedure CopyFile();
begin
FileCopy('{OutputDir}/{OutputBaseFilename}',
'V:/Service/Software/ASCDeploy/Prod/Asc.Tools.FileCopy/{OutputBaseFilename}', False);
end;
There's no way to run any code after Inno Setup finishes compiling - At least not in the original Inno Setup.
See also Inno Setup - Post Processing.

Inno Setup: Download setup .bin slice files before installation starts

I am trying to create a distributable .exe file with Inno Setup tools and Inno Download Plugin. The resulting file is ~3GB in size, split in 6 parts (1 for the executable, 5 bins containing all the files).
Would it be possible to keep the 5 bins uploaded on some server and download them during installation with the remaining executable file?
My code is here :
procedure InitializeWizard();
var
ResultCode: integer;
TempAddress: String;
FinalSavePath: String;
UserName, UserCompany: String;
begin
idpSetOption('DetailedMode', '1');
idpSetOption('AllowContinue', '1');
idpSetLogin('aaa', 'aaa');
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpDownloadAfter(wpWelcome);
end;
With idpDownloadAfter(wpWelcome) the installer starts downloading right after accepting to run the executable, if .bin files are already present. If not, the installer just keeps asking for the .bin to be present.
Inno Setup 6.1 has a built-in support for file downloads, which does not need any support files. So the solution below is obsolete now. See Inno Setup: Install file from Internet.
Inno Download Plugin uses idp.dll, which itself is stored in the mysetup-*.bin files. That's why you get prompted for the .bin files, even before anything starts. You need the idp.dll so that the download itself can start.
With some hacking you can have the idp.dll be stored in the [Code], hence directly in the mysetup.exe.
See Inno Setup: Reading a file from installer during uninstallation.
You will need to modify the idp.iss as follows:
Remove the [Files] section with its reference to idp.dll.
In all the external functions declarations:
change #files:idp.dll cdecl to #{tmp}\idp.dll cdecl delayload.
To the front of your .iss script, copy the long code block from my answer to the previously mentioned question.
And now you can do:
procedure InitializeWizard();
begin
SaveBinaryStringToFile(
ExpandConstant('{tmp}\idp.dll'), {#FileToBinaryString("unicode\idp.dll")});
idpAddFile(
'https://www.example.com/mysetup-1.bin', ExpandConstant('{src}\mysetup-1.bin'));
idpDownloadAfter( {whatever} );
end;
Make sure you update the path to the idp.dll to the correct location on your development machine in the call to FileToBinaryString.
The code is for Unicode version of Inno Setup (the only version as of Inno Setup 6).

Inno Setup Call AfterInstall for each external File

I am really struggling with this one. I have an entry in the files section of an Inno Setup (5.5.9) configuration file, that is something like the following:
[Code]
procedure showMsgBoxOfFile;
begin
MsgBox(ExpandConstant(CurrentFilename), mbInformation, MB_OK);
end;
[Files]
Source: {src}\Some\Path\myFile*Pattern.ext; DestDir: {app}; Flags: external; \
AfterInstall: showMsgBoxOfFile;
When I run the installer generated by running the above script, I get a single message box with the {app} directory, even though four files are copied. This seems to be in direct contradiction of the Inno Setup documentation on BeforeInstall/AfterInstall, which states:
A BeforeInstall or AfterInstall function for a [Files] section entry using a wildcard is called once per file matching the wildcard. Use CurrentFileName to check for which file the function is called.
Further, another question on Stack Overflow is from a user who wanted to do the exact opposite (get only one notification when multiple files were changed). The accepted answer to that question indicates that:
there is no way to call [AfterInstall] once after all the files are installed
I noticed that if I remove the "external" flag from my file copy, I DO get one message box per file. Is there a way to get a one notification per copied file when the "external" flag is specified? Does anyone know if there is a plan to document this difference in the Inno Setup help files?
Indeed, for entries with the external flag, the BeforeInstall and AnswerInstall functions are called only once.
What you can do, is to copy the files programmatically. It would give you a full control over, what you do for each file.
See Inno Setup: copy folder, subfolders and files recursively in Code section

Make Inno Setup automatically add data from custom pages to .inf file

I created a installer with custom wizard pages. All works fine so far.
Next I wanted to create a settings file using /SAVEINF (to start the installer later on in silent mode) using the following command:
Installer.exe /SAVEINF="Unattended.txt"
After entering all user input and running the installer, I looked at the file created. The only user input I see is the installation location but missing all my input on the custom wizard pages. All I see is:
[Setup]
Lang=en
Dir=C:\temp
Group=MyProgram
NoIcons=0
Tasks=
Why? What do I need to do to have the custom wizard page values also in the settings file?
To be more specific.
I start the installer I've created with option to create a settings file using the /SAVEINF option on the commandline. I expected all items to be added to this file including the one from my custom wizard pages, but that's not the case. I only see the installation location from the standard setup page.
Of course I can add them manually and implement in the installer code to read them from the file, but I expected it to be automated.
Indeed, Inno Setup won't save any custom fields to the .inf file.
It will never save anything to the .inf file beyond the standard Lang, Dir, Group, NoIcons, SetupType, Components and Tasks items.
See SaveInf function in Inno Setup source code:
procedure SaveInf(const FileName: String);
const
Section = 'Setup';
begin
SetIniString(Section, 'Lang',
PSetupLanguageEntry(Entries[seLanguage][ActiveLanguage]).Name, FileName);
SetIniString(Section, 'Dir', WizardDirValue, FileName);
SetIniString(Section, 'Group', WizardGroupValue, FileName);
SetIniBool(Section, 'NoIcons', WizardNoIcons, FileName);
if WizardSetupType <> nil then begin
SetIniString(Section, 'SetupType', WizardSetupType.Name, FileName);
SetIniString(Section, 'Components', StringsToCommaString(WizardComponents), FileName);
end
else begin
DeleteIniEntry(Section, 'SetupType', FileName);
DeleteIniEntry(Section, 'Components', FileName);
end;
SetIniString(Section, 'Tasks', StringsToCommaString(WizardTasks), FileName);
end;
There are more items Inno Setup will load from the .inf file. See the LoadInf function. But again, not custom fields/pages. Just options that can otherwise be specified using command-line switches, like Silent, VerySilent, NoRestart, etc.
If you want custom fields in the .inf file, you have to implement them on your own:
Inno Setup Load defaults for custom installation settings from a file (.inf) for silent installation.

How to configure Inno Setup to uninstall everything?

I am new to Inno Setup. Stuck on one issue ~ how to configure the uninstall piece to remove all files, folders, subfolders, and even new files/folders etc. created by application (in other words, a 100% removal of the application and associated files).
I hunted around here and also on their forum, and came up empty. Can anyone point me to a document, FAQ etc. regarding how to do this?
UPDATE
Thanks for all the feedback so far (very awesome). So it looks like I can delete everything using the {app}*.* directive in the uninstall section. Also looks like everyone is advising against it. So the question now becomes (I am wondering if this should be a totally new question) is there a way during the uninstall that we can ask the user 'Do you want to remove all project files associated with this application?' and if they answer YES, to run the uninstall {app}*.* piece?
Thanks -
I think the recommended approach is to specify what to remove in the uninstall section. The reasoning is that what if for whatever reason the user decided to put their own files in your installation directory that they didn't want removed, or saved data that they might want to keep around (maybe they uninstall is to install a newer version?)
That being said, I don't know offhand what the script is, but if you use ISTool (highly recommend) just got to the Uninstall Delete section and add things you want removed. It should present all the possible options in a nice GUI and generate the script for you.
Edit: An example from the Inno Setup documentation:
[UninstallDelete]
Type: files; Name: "{win}\MYPROG.INI"
But they strongly you don't do something like
[UninstallDelete]
Type: files; Name: "{app}\*.*"
NOTE: Don't be tempted to use a wildcard here to delete all files in
the {app} directory. I strongly
recommend against doing this for two
reasons. First, users usually don't
appreciate having their data files
they put in the application directory
deleted without warning (they might
only be uninstalling it because they
want to move it to a different drive,
for example). It's better to leave it
up to the end users to manually remove
them if they want. Also, if the user
happened to install the program in the
wrong directory by mistake (for
example, C:\WINDOWS) and then went to
uninstall it there could be disastrous
consequences. So again, DON'T DO THIS!
You should probably have made this a totally new question, but I'll answer your updated question here as well. Have a look at the section "Pascal Scripting: Uninstall Code" in the Inno Setup Documentation.
To give an example how to conditionally delete data files as part of the uninstallation process:
[Code]
procedure DeleteBitmaps(ADirName: string);
var
FindRec: TFindRec;
begin
if FindFirst(ADirName + '\*.*', FindRec) then begin
try
repeat
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then begin
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin
DeleteBitmaps(ADirName + '\' + FindRec.Name);
RemoveDir(ADirName + '\' + FindRec.Name);
end;
end else if Pos('.bmp', AnsiLowerCase(FindRec.Name)) > 0 then
DeleteFile(ADirName + '\' + FindRec.Name);
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then begin
if MsgBox('Do you want to delete all data files?', mbConfirmation,
MB_YESNO) = IDYES
then begin
DeleteBitmaps(ExpandConstant('{app}'));
end;
end;
end;
But depending on the amount of stuff you need to clean up you might be better off to create a special helper program that is part of the installation, and which can be executed during the uninstallation of the app (using an entry in the [UninstallRun] section).
There are cases to want to delete files which were not initially written to the user's disk at time of installation. One of these cases is when you have an application that updates itself when it is started. New files can be added to the disk in this manner which are not a part of the uninstaller.
For this case I suggest that you create a "patch manifest" file which keeps a running record of what files should be in the {app} directory. Find below a sample of code that reads from a file in the {app} dir called 'patch_manifest.txt'
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
i: Integer;
arrayLen: Longint;
item: String;
itemsToDelete: Array of String;
begin
case CurUninstallStep of
usUninstall:
begin
LoadStringsFromFile(ExpandConstant('{app}') + '\patch_manifest.txt', itemsToDelete);
arrayLen := GetArrayLength(itemsToDelete);
for i := 0 to arrayLen-1 do
begin
item := ExpandConstant('{app}') + '\' + itemsToDelete[i];
if FileExists(item) then
DeleteFile(item);
if DirExists(item) then
RemoveDir(item);
end;
end;
end;
end;
and a sample of the patch_manifest.txt
data/something_here.dat
data/moredatahere.dat
data/
Launcher.exe
patch_manifest.txt
Note: The order of the lines in the patch_manifest is important. All files within a directory should first be listed followed by the directory - directories which are not empty cannot be delete.
Your application should be shipped with a patch_manifest and the patch_manifest should be updated with every patch. Make this part of your build process so you don't forget to update it!
It is very important that you do not delete by wildcard (.) even if you prompt the user. Uninstaller's have elevated privileges which could potentially destroy a user's computer. Take the case of a user who accidentally installed your application to C:\Windows\ or C:\Program Files.
Another good idea is to verify that the file is in fact "your file" by performing an MD5 check prior to deleting it. In this case your patch_manifest.txt would not only include the relative path to the file but also the MD5 checksum.
You can't use InnoSetup to uninstall anything it didn't install, and you shouldn't want to do so. I for one would be very unhappy if I installed an application, entered a lot of data, and then decided to use something else instead that would read that data from your app. If your uninstall killed all of the work I'd already done, I might be tempted to come looking for you. And probably not to buy you a cup of coffee.
Or consider the case where I install your application in the process of evaluating several. I try the apps, and keep going back to yours because I like it a little better, and each time I enter more data. Then I decide not to do anything for a while, so I remove all the test apps. In a week, I decide I need to use your app now after all, and I reinstall it. Oops! All of the work I did testing it that I now wanted to use is gone.
The above is why, when you uninstall an application, it leaves behind anything you created in the folders, like configuration files, data files, etc. It doesn't know what you want it to do with them, so it leaves them alone.
This should do the trick:
[Dirs]
Name: "{app}"; Flags: uninsalwaysuninstall
Add delete file/folder item in Inno Setup studio. Or directly use the script as follows.
[Generated code sample]
[UninstallDelete]
Type: filesandordirs; Name: "{app}\unnecessary_files"
I wanted to delete gData.dat which created on run time in installed folder
and was working fine for me
[UninstallDelete]
Type: files; Name: "{app}\gData.dat"
Isn't that the default if your don't specify "uninsneveruninstall" for an entry?
edit - Sorry I hadn't realised you were talking about newly created data files.
To delete everything I use this :
[UninstallDelete]
Type:files; Name: "{app}"

Resources