How to get Inno Setup to unzip a file it installed (all as part of the one installation process) - zip

To save bandwidth/space as well as prevent accidental meddling, the installation files for a database product (call it Ajax), have been zipped up (call that file "AJAX_Install_Files.ZIP). I would like to have Inno-Setup "install" (i.e., copy) the AJAX_Install_Files.ZIP file to the destination, and then Unzip the files into the same folder where the .ZIP file is located. A subsequent program would be fired off by Inno Setup to actually run the install of product "Ajax".
I've looked through the documentation, FAQ, and KB at the Inno Setup website, and this does not seem possible other than writing a Pascal script (code) - would that be correct, or are there are any alternative solutions?

You can use an external command line tool for unzipping your archive, see here for example. Put it in your [Files] section:
[Files]
Source: "UNZIP.EXE"; DestDir: "{tmp}"; Flags: deleteafterinstall
Then call it in your [Run] section, like this:
[Run]
Filename: "{tmp}\UNZIP.EXE"; Parameters: "{tmp}\ZipFile.ZIP -d C:\TargetDir"
(You'll probably want to take your target directory from a script variable, so there is some more work that needs to be done)

You can use the shell Folder.CopyHere method to extract a ZIP.
const
SHCONTCH_NOPROGRESSBOX = 4;
SHCONTCH_RESPONDYESTOALL = 16;
procedure UnZip(ZipPath, TargetPath: string);
var
Shell: Variant;
ZipFile: Variant;
TargetFolder: Variant;
begin
Shell := CreateOleObject('Shell.Application');
ZipFile := Shell.NameSpace(ZipPath);
if VarIsClear(ZipFile) then
RaiseException(
Format('ZIP file "%s" does not exist or cannot be opened', [ZipPath]));
TargetFolder := Shell.NameSpace(TargetPath);
if VarIsClear(TargetFolder) then
RaiseException(Format('Target path "%s" does not exist', [TargetPath]));
TargetFolder.CopyHere(
ZipFile.Items, SHCONTCH_NOPROGRESSBOX or SHCONTCH_RESPONDYESTOALL);
end;
Note that the flags SHCONTCH_NOPROGRESSBOX and SHCONTCH_RESPONDYESTOALL work on Windows Vista and newer.
For an example of extracting some files only, see:
How to get Inno Setup to unzip a single file?

I answered a very similar question and some of the details apply.
I would question why you need a ZIP file of the contents? I personally would place the uncompressed files into the setup. I would then have two [category] entries one for the application and one for the data. Default both the be checked.
This would allow the users to install a fresh set of the data if needed at a later date.
If you really want a ZIP file and want to keep it easy you could, ship both the zip files and the uncompressed files in the same setup.
Update:
By default files that get placed in your setup.exe are compressed.
You can also have the files extracted to a temporary location so you can run your
installation application, then have them deleted.
[Files]
Source: "Install1.SQL"; DestDir: "{tmp}"; Flags:deleteafterinstall;
Source: "Install2.SQL"; DestDir: "{tmp}"; Flags:deleteafterinstall;

You can just create silent self-extracting archive (SFX) archive, example described here how to create SFX archive for stuff you need, and write Pascal code to just run it like this (script for Inno Setup 6.0.2):
[Tasks]
Name: "intallSenselockDriver"; Description: "Install Senselock driver."; GroupDescription: "Install the necessary software:";
[Code]
function ExecTmpFile(FileName: String): Boolean;
var
ResultCode: Integer;
begin
if not Exec(ExpandConstant('{tmp}\' + FileName), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode)
then
begin
MsgBox('Other installer failed to run!' + #13#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
Result := False;
end
else
Result := True;
end;
procedure RunOtherInstallerSFX(ArchiveName: String; ExePath: String);
begin
ExtractTemporaryFile(ArchiveName);
ExecTmpFile(ArchiveName);
ExecTmpFile(ExePath);
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
if WizardIsTaskSelected('intallSenselockDriver') then
RunOtherInstallerSFX('1_senselock_windows_3.1.0.0.exe', '1_senselock_windows_3.1.0.0\InstWiz3.exe');
Result := '';
end;
It worked perfectly for me.

Using Double quotes worked for me.
Single quotes were not working.
[Files]
Source: "unzip.exe"; DestDir: "{userappdata}\{#MyAppName}\{#InputFolderName}"; Flags: ignoreversion
[Run]
Filename: "{userappdata}\{#MyAppName}\{#InputFolderName}\unzip.exe"; Parameters: " ""{userappdata}\{#MyAppName}\{#InputFolderName}\ZIPFILENAME.zip"" -d ""{userappdata}\{#MyAppName}\{#InputFolderName}"" "; Flags: runascurrentuser

Related

Generate a configuration file with an entry for each selection using Inno Setup [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Based on what I pick in Inno Setup, the installer should add an entry containing package name followed by , into config.ini
And extract the right premade config files (that are stored in the installer) needed for the few specific setups into the Config folder.
There are plenty of programs like Chrome/Firefox which don't need any parameters or additional configs to install.
Desired config.ini file syntax:
<package1>, <package2 /X /Y /Z>, <package 3> ...
Etc.
Where <packageX> is a string value tied to the checkboxes in the installer selection menu.
After Inno Setup completes, it should run a batch file.
Bonus points: Again.. not only output the config.ini, BUT also extract necessary premade configs set-up for the specific program into a folder C:/NKsetup/Config/
Add each each of your packages as a component to the Components section. Then in the Files section, you can choose what files get installed based on the components selected. For the packages list config file, you need to code that with use of the WizardIsComponentSelected function.
[Setup]
DefaultDirName=C:\some\path
[Types]
Name: "custom"; Description: "-"; Flags: iscustom
[Components]
Name: "sqlserver"; Description: "Microsoft SQL server"
Name: "chrome"; Description: "Google Chrome"
Name: "firefox"; Description: "Mozilla Firefox"
[Files]
Source: "install.bat"; DestDir: "{app}"
Source: "common-config.ini"; DestDir: "{app}"
Source: "sqlserver-config.ini"; DestDir: "{app}"; Components: sqlserver
Source: "browsers-config.ini"; DestDir: "{app}"; Components: chrome firefox
[Run]
Filename: "{app}\install.bat"; StatusMsg: "Installing..."
[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
ConfigPath: string;
Packages: string;
begin
if CurStep = ssPostInstall then
begin
if WizardIsComponentSelected('sqlserver') then
begin
Packages := Packages + ',sql-server-express /X /Y /Z';
end;
if WizardIsComponentSelected('chrome') then
begin
Packages := Packages + ',chrome';
end;
if WizardIsComponentSelected('firefox') then
begin
Packages := Packages + ',firefox';
end;
// Remove the leading comma
if Packages <> '' then
begin
Delete(Packages, 1, 1);
end;
ConfigPath := ExpandConstant('{app}\config.ini');
// This is not Unicode-safe
if not SaveStringToFile(ConfigPath, Packages, False) then
begin
Log(Format('Error saving packages to %s', [ConfigPath]));
end
else
begin
Log(Format('Packages saved to %s: %s', [ConfigPath, Packages]));
end;
end;
end;

inno setup to browse and extract zip file at sepcific location

I want to enable users to browse and extract zip files at a specific location.
Requirements/steps:
Display welcome page
Next display browse button to select installation directory(DisableDirPage=no)
Next display browse button to select zip file(JDK)
Extract JDK zip file selected in step 3 at location selected in step 2, that means JDK should be extracted in installation directory that user selects in step 2
Problems with my code:
After the first step my code directly jump into 3rd step and then it goes to 2nd.
The code to extract zip is not working if I pass method name as the parameter. If I pass the hardcoded value of the location it works. I don't know pascal and it basically seems to be a syntax related issue.
[SETUP]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
DisableProgramGroupPage=no
DisableWelcomePage=no
DisableDirPage=no
Compression=lzma2
SolidCompression=yes
OutputDir=userdocs:Inno Setup Examples Output
[Files]
Source: "{code:GetLicensePath}"; DestDir: "{app}"; Flags: external
Source: "7za.exe"; DestDir: "D:\authorized\Builds\Solo\"; Flags: deleteafterinstall;
[Icons]
Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"
[Run]
Filename: D:\authorized\Builds\Solo\7za.exe; Parameters: "x ""{{Code:GetZipPath}}"" -o""{app}\"" * -r -aoa"; Flags: runhidden runascurrentuser;
[Code]
var
Page: TInputFileWizardPage;
DataDir:String;
procedure InitializeWizard();
begin
Page :=
CreateInputFilePage(
wpWelcome,
'Select Zip File Location',
'Where is your Zip file located?',
'Select where Zip file is located, then click Next.');
Page.Add(
'Location of Zip file:',
'*.7z|*.rar|All files|*.*',
'.zip');
// Set initial value (optional)
Page.Values[0] := ExpandConstant('{%USERPROFILE}\Downloads\setup.7z');
;
end;
function GetZipPath(Param: string): string;
begin
DataDir := Page.Values[0];
end;
Could you help me, please?
The order of your custom page is determined by the first argument of the Create* function. So change wpWelcome to wpSelectDir.
Why double {{...}} - That’s likely the problem. Also code: should be lowercase.
Your scripted constant function does not really return anything. It should be:
Result := Page.Values[0];

Inno Setup - Avoid displaying filenames of sub-installers

I am trying to use the idea from Inno Setup - How to hide certain filenames while installing? (FilenameLabel)
The only sure solution is to avoid installing the files, you do not want to show, using the [Files] section. Install them using a code instead. Use the ExtractTemporaryFile and FileCopy functions
But the files that I want to hide are using in the [Run] Section:
[Files]
Source: "_Redist\DXWebSetup.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
[Run]
Filename: "{tmp}\DXWebSetup.exe"; Components: DirectX; StatusMsg: "Installing DirectX..."; \
BeforeInstall: StartWaitingForDirectXWindow; AfterInstall: StopWaitingForDirectXWindow
How to hide (while installing, in filenamelabel) using [Files] section, ExtractTemporaryFile and FileCopy functions?
The easiest is to give up on the standard [Files] and [Run] sections and code everything on your own in the CurStepChanged event fuction:
[Files]
Source: "dxwebsetup.exe"; Flags: dontcopy
[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
ProgressPage: TOutputProgressWizardPage;
ResultCode: Integer;
begin
if CurStep = ssInstall then { or maybe ssPostInstall }
begin
if IsComponentSelected('DirectX') then
begin
ProgressPage := CreateOutputProgressPage('Installing prerequsities', '');
ProgressPage.SetText('Installing DirectX...', '');
ProgressPage.Show;
try
ExtractTemporaryFile('dxwebsetup.exe');
StartWaitingForDirectXWindow;
Exec(ExpandConstant('{tmp}\dxwebsetup.exe'), '', '', SW_SHOW,
ewWaitUntilTerminated, ResultCode);
finally
StopWaitingForDirectXWindow;
ProgressPage.Hide;
end;
end;
end;
end;
This even gives you a chance to check for results of the sub-installer. And you can e.g. prevent the installation from continuing, when the sub-installer fails or is cancelled.
Then it's easier to use the PrepareToInstall instead of the CurStepChanged.
Another option is to display a custom label, while extracting the sub-installer.
See Inno Setup - How to create a personalized FilenameLabel with the names I want?

Inno Setup Runtime error while accessing CurrentFileName when installing an empty folder

I tried to access all files inside a folder through Pascal code. When I iterate through an empty folder I am getting the following error:
Exception: Internal error; An attempt was made to call the "CurrentFileName" function from outside a "Check", "BeforeInstall" or "AfterInstall" event function belonging to a "[Files]" entry
The code I used:
[Files]
Source: ".\3D_Dlls\*"; DestDir: {app}\3D_Dlls; \
Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist; \
Check: FileBackup
[Code]
function FileBackup(): Boolean;
var FileName,Source,Target,TargetDir: String;
begin
Result := True;
Source := ExpandConstant(CurrentFileName);
end
Say for example my folder structure is like that:
3D_Dlls
- Folder 1
- Folder 2 // Empty folder and it invokes the problem
- Folder 3
I believe this is a bug in Inno Setup triggered by the createallsubdirs flag.
When the flag is specified, Inno Setup collects a separate list of empty directories that need to be explicitly created during an installation. When "installing" the empty folder, the call to the CurrentFileName simply fails.
Workarounds:
Remove the createallsubdirs flag, if possible.
Instead, you can explicitly create empty directories using the [Dirs] section.
Catch the exception:
function FileBackup: Boolean;
begin
Result := True;
try
Source := ExpandConstant(CurrentFileName);
except
Log(GetExceptionMessage);
end;
end;
I have reported this on Inno Setup newsgroup, but the newsgroup was reset since.

Inno Setup: Install file from Internet

I am using Inno Setup to distribute my application.
Is it possible to check in Inno Script for a particular condition and download and install some file from internet if required.
Inno Setup 6.1 and newer has a built-in support for downloads. No 3rd party solution are needed anymore.
Check the Examples\CodeDownloadFiles.iss in Inno Setup installation folder.
The important parts of the example are:
[Files]
; These files will be downloaded
Source: "{tmp}\innosetup-latest.exe"; DestDir: "{app}"; Flags: external
Source: "{tmp}\ISCrypt.dll"; DestDir: "{app}"; Flags: external
[Code]
var
DownloadPage: TDownloadWizardPage;
function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;
begin
if Progress = ProgressMax then
Log(Format('Successfully downloaded file to {tmp}: %s', [FileName]));
Result := True;
end;
procedure InitializeWizard;
begin
DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), #OnDownloadProgress);
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
if CurPageID = wpReady then begin
DownloadPage.Clear;
DownloadPage.Add('https://jrsoftware.org/download.php/is.exe', 'innosetup-latest.exe', '');
DownloadPage.Add('https://jrsoftware.org/download.php/iscrypt.dll', 'ISCrypt.dll', '2f6294f9aa09f59a574b5dcd33be54e16b39377984f3d5658cda44950fa0f8fc');
DownloadPage.Show;
try
try
DownloadPage.Download;
Result := True;
except
SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK);
Result := False;
end;
finally
DownloadPage.Hide;
end;
end else
Result := True;
end;
For alternatives, see Running a program after it is downloaded in Code section in Inno Setup
Inno Download Plugin by Mitrich Software.
It's an InnoSetup script and DLL, which allows you to download files as part of your installation.
It supports FTP, HTTP and HTTPS.
It's kind of a drop-in replacement for InnoTools Downloader. Only few changes required.
It brings a decent download display and HTTPS and Mirror(s) support.
Example:
#include <idp.iss>
[Files]
Source: "{tmp}\file.zip"; DestDir: "{app}"; Flags: external; ExternalSize: 1048576
[Code]
procedure InitializeWizard();
begin
idpAddFileSize('http://127.0.0.1/file.zip', ExpandConstant('{tmp}\file.zip'), 1048576);
idpDownloadAfter(wpReady);
end.
Yes, there is a library called InnoTools Downloader which has samples that do pretty much this. They can be conditioned on anything you want using normal Inno code.
Found on Inno 3rd Party is one very similar in scope and style to the Inno Download Plugin, DWinsHs.
Included with an easy and intuitive chm file which requires unblocking to view.

Resources