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

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.

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).

Is there a way to extract .zip files in Inno Setup after a certain page is done?

So I basically have a .zip file in my {tmp} directory, and want to extract it's contents in {tmp} but only when my third form is done with it's work, not earlier. The reason is: Because in the third form I download this .zip from the internet and it is saved into {tmp}. Now after this I want to extract these files into {tmp} from which I am to get the files from the extracted folders, like the release notes, license agreement files to use in the rest of the forms in the installer. Meaning, already in the form after the third one, I am using the files extracted.
I can't find anywhere how to do this after a certain form. I only found in the run section how extracting is done.
EDIT: The old way I described proved not to work well on some Windows versions. It may pop up a dialog window instead of overwriting files silently. This is easy to google: CopyHere ignores options.
The new way:
Mitchich Inno Download plugin
7zip
The new way uses 7zip standalone console version. It is a single 7za.exe, you don't need the DLLs.
#include <idp.iss>
; Languages section
; Includes for Mitrich plugin's additional languages
; #include <idplang\Russian.iss>
[Files]
Source: "7za.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall;
[Run]
Filename: {tmp}\7za.exe; Parameters: "x ""{tmp}\example.zip"" -o""{app}\"" * -r -aoa"; Flags: runhidden runascurrentuser;
[Code]
procedure InitializeWizard;
begin
idpAddFile('https://example.comt/example.zip', ExpandConstant('{tmp}\example.zip'));
{ Download after "Ready" wizard page }
idpDownloadAfter(wpReady);
end;
If you want to download, unzip and use files (for example, as license agreement) before the installation starts, I can only give the general guideline:
Enable welcome page in [Setup]: DisableWelcomePage=no.
Use idpDownloadAfter(wpWelcome);. Now it downloads right after "Welcome" page.
You need an empty license file in [Setup]: LicenseFile=license.txt for license page to show up. Or probably not empty, but with "Loading license agreement..." text.
You implement procedure CurPageChanged(): if current page is wpLicense then you call Exec() function to launch 7zip and wait for it to terminate. No 7zip in [Run] section now. Then you probably use LoadStringFromFile() function to get license agreement from extracted file. Then put it into UI. Probably WizardForm.LicenseMemo.RTFText = ... should work. Anyway, UI is accessible, if you have trouble setting the text, ask a separate question on this.
The old buggy way:
Mitchich Inno Download plugin
Inno Unzip Plugin
An equivalent, cleaner way without unzipper.dll is described here. One way or another, it uses buggy CopyHere Windows feature.
#include <idp.iss>
; Languages section
; Includes for Mitrich plugin's additional languages
; #include <idplang\Russian.iss>
[Files]
Source: "unzipper.dll"; Flags: dontcopy
[Code]
procedure InitializeWizard;
begin
idpAddFile('https://example.comt/example.zip', ExpandConstant('{tmp}\example.zip'));
{ Download after "Ready" wizard page }
idpDownloadAfter(wpReady);
end;
procedure unzip(src, target: AnsiString);
external 'unzip#files:unzipper.dll stdcall delayload';
procedure ExtractMe(src, target : AnsiString);
begin
unzip(ExpandConstant(src), ExpandConstant(target));
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
{ Extract when "Finishing installation" setup step is being performed. }
{ Extraction crashes if the output dir does not exist. }
{ If so, create it first: }
{ CreateDir(ExpandConstant(...)); }
ExtractMe('{tmp}\example.zip', '{app}\');
end;
end;
You can probably try other things instead of wpReady and ssPostInstall. For my small zip this works well.

Checking existence of a file in Inno Setup Internal Temporary folder

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))

Can I put setup command line parameters in a file which is called during installation instead?

After creating my setup.exe I have to pack it for various software deployment tools. Therefore I can't call the setup.exe with parameters, instead I have placed my own parameters in a setup.ini file next to the setup.exe
[Code]
var
MyIniFile: String;
function InitializeSetup(): Boolean;
var
LoadFromIniFile: String;
begin
Result := true;
MyIniFile := ExpandConstant('{srcexe}'); //writes the full path of the setup.exe in "MyIniFile"
MyIniFile := Copy(MyIniFile, 1, Length(MyIniFile) - Length(ExtractFileExt(MyIniFile))) + '.ini'; //changes the ".exe" into ".ini"
if FileExists(MyIniFile) then LoadFromIniFile := MyIniFile; //checks wether there is a ini-file
if LoadFromIniFile <> '' then begin
MyLogFile := GetIniString('Setup', 'Log', MyLogFile , LoadFromIniFile);
ProductName := GetIniString('Setup', 'ProductName', ProductName, LoadFromIniFile);
end;
end;
Now I want to also place the so called "Setup Command Line Parameters" (listed on the Inno Setup Help site) in my ini-file. I think that there is a way for the /Dir="x:\dirname parameter, which I did not figure out yet. But I also want to have the /SILENT parameter in there, do you think there is a way to do this? If yes, how would you do this? If not, can you please give me a hint why not?
So customize your installer for different products, I'd recommend you to use a pre-processor and automatically build the installer for each product (with different "defines"), instead of using an external INI file.
For example to be able to change application name and resulting executable when building the installer, use a script like:
[Setup]
AppName={#AppName}
OutputBaseFilename={#BaseFilename}
Now you can create two different installers automatically using command-line:
ISCC.exe Example1.iss /dAppName=App1 /dBaseFilename=SetupApp1
ISCC.exe Example1.iss /dAppName=App2 /dBaseFilename=SetupApp2
Regarding the implicit silent installation:
There's no API other than the command-line /SILENT switch to trigger silent installation.
But you can create a near-silent installation by disabling most installer pages:
[Setup]
DisableWelcomePage=true
DisableDirPage=true
DisableProgramGroupPage=true
DisableReadyPage=true
DisableFinishedPage=true
Actually the above example disables all default pages. But Inno Setup compiler will ignore the DisableReadyPage=true, if all other previous pages are disabled.
You may want to choose a different page to show instead. For example a Welcome page (by omitting DisableWelcomePage=true, but keeping the DisableReadyPage=true).
If you do not mind about using external files (as you already use an external INI file), you can of course wrap the installer to a batch file and call the installer with the /SILENT switch.

Resources