I have the following code in my Inno Setup script:
[Files]
Source: "C:\Users\Myname\Documents\Visual Studio
2010\Redistributional\vcredist_x86.exe"; DestDir: "{tmp}"; Flags:
deleteafterinstall;
Source: "C:\Users\Myname\Documents\Visual Studio
2010\Redistributional\vcredist_x64.exe"; DestDir: "{tmp}"; Flags:
deleteafterinstall;
[Run]
Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/install /passive"; Check:
not IsWin64 and not VCinstalled32
Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/install /passive"; Check:
IsWin64 and not VCinstalled64
Filename: "{app}\Myprogram.exe"; Description {cm:LaunchProgram,Myprogram}";
[Code]
function VCinstalled32: Boolean;
var
installed: Cardinal;
key: String;
begin
Result := False;
key := 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x86';
if DirExists
('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x86')
then begin
if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Installed', installed)
then begin
if installed = 1 then begin
Result := True;
end;
end;
end;
end;
function VCinstalled64: Boolean;
var
installed: Cardinal;
key: String;
begin
Result := False;
key := 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x64';
if DirExists
('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x64')
then begin
if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Installed', installed)
then begin
if installed = 1 then begin
Result := True;
end;
end;
end;
end;
I have tried to run this on a 64 bits Windows 10 machine in which the directory HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x64 does not exist, but I get an error message saying that MSVCR100 is not found.
Thanks in advance.
Update
Thank you very much for you answer, but still I get the same error message. Maybe I have overlooked something.
Update
I am not very acquainted with Inno script and don't know anything about how to log the result. I have tried to google the latter, but it seems to be very complicated, so I'll try to wait with this to later, if I can't find the answer in any other way.
Update
Here is some of the output from the Log file:
2018-03-05 14:01:03.567 -- File entry --
2018-03-05 14:01:03.568 Dest filename: C:\Users\Bruker\AppData\Local\Temp\is-SP07M.tmp\vcredist_x86.exe
2018-03-05 14:01:03.568 Time stamp of our file: 2018-02-18 14:27:32.000
2018-03-05 14:01:03.568 Installing the file.
2018-03-05 14:01:04.016 Successfully installed the file.
2018-03-05 14:01:04.017 -- File entry --
2018-03-05 14:01:04.018 Dest filename: C:\Users\Bruker\AppData\Local\Temp\is-SP07M.tmp\vcredist_x64.exe
2018-03-05 14:01:04.018 Time stamp of our file: 2018-02-18 16:00:00.000
2018-03-05 14:01:04.018 Installing the file.
2018-03-05 14:01:04.937 Successfully installed the file.
2018-03-05 14:01:08.883 -- Run entry --
2018-03-05 14:01:08.883 Run as: Current user
2018-03-05 14:01:08.883 Type: Exec
2018-03-05 14:01:08.883 Filename: C:\Users\Bruker\AppData\Local\Temp\is-SP07M.tmp\vcredist_x64.exe
2018-03-05 14:01:08.883 Parameters: /install /passive
2018-03-05 14:01:21.800 Process exit code: 0
2018-03-05 14:01:21.800 -- Run entry --
2018-03-05 14:01:21.800 Run as: Current user
2018-03-05 14:01:21.800 Type: Exec
2018-03-05 14:01:21.800 Filename: C:\Program Files (x86)\Myfile\myfile.exe
2018-03-05 14:01:28.020 Process exit code: 3221225781
2018-03-05 14:01:28.023 Need to restart Windows? No
2018-03-05 14:01:30.504 Deinitializing Setup.
2018-03-05 14:01:30.593 Log closed.
As I have understood, Process exit code: 0 means that the file has executed successfully, so I still don't understand what could be wrong.
I just read up on MSVCR100.DLL:
MSVCR100.dll = Visual Studio 2010 Runtime
MSVCR110.dll = Visual Studio 2012 Runtime
MSVCR120.dll = Visual Studio 2013 Runtime
So are you actually installing the correct redistributables?
With respects to your script, why are you using DirExists? That is designed to verify if a directory exists. You are working with the registry so you should be using RegKeyExists. The help provides an example:
begin
if RegKeyExists(HKEY_CURRENT_USER, 'Software\Jordan Russell\Inno Setup') then
begin
// The key exists
end;
end;
I have not tested this but you would want something like:
function VCinstalled64: Boolean;
var
installed: Cardinal;
key: String;
begin
Result := False;
key := 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\Runtimes\x64';
if RegKeyExists(HKEY_LOCAL_MACHINE, key) then
begin
if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Installed', installed)
then begin
if installed = 1 then begin
Result := True;
end;
end;
end;
end;
The other method VCinstalled32 would need similar changes.
Logging
The help system supplied with Inno Setup (also online) explains about logging:
/LOG
Causes Setup to create a log file in the user's TEMP directory detailing file installation and [Run] actions taken during the installation process. This can be a helpful debugging aid. For example, if you suspect a file isn't being replaced when you believe it should be (or vice versa), the log file will tell you if the file was really skipped, and why.
The log file is created with a unique name based on the current date. (It will not overwrite or append to existing files.)
The information contained in the log file is technical in nature and therefore not intended to be understandable by end users. Nor is it designed to be machine-parsable; the format of the file is subject to change without notice.
/LOG="filename"
Same as /LOG, except it allows you to specify a fixed path/filename to use for the log file. If a file with the specified name already exists it will be overwritten. If the file cannot be created, Setup will abort with an error message.
So, from the Windows Start Menu type in the box cmd and click on Command Prompt:
Next, navigate to the folder where the installer is and run it with the /log parameter:
Edit your question and add the output from the log to it. Also consider replacing your snippet of script with your complete script (the original script that used DirExists.
I have done a bit more research and found this interesting question. If you look at your log output it only installs the 64 bit edition:
2018-03-05 14:01:08.883 -- Run entry --
2018-03-05 14:01:08.883 Run as: Current user
2018-03-05 14:01:08.883 Type: Exec
2018-03-05 14:01:08.883 Filename: C:\Users\Bruker\AppData\Local\Temp\is-SP07M.tmp\vcredist_x64.exe
2018-03-05 14:01:08.883 Parameters: /install /passive
2018-03-05 14:01:21.800 Process exit code: 0
Change this line from:
Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/install /passive"; Check: not IsWin64 and not VCinstalled32
to:
Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/install /passive"; Check: not VCinstalled32
Your executable appears to be 32 bit, and based on that question I referred to it states:
No, you need the x86 version to run 32-bit VC++ programs, and you need the x64 version to run 64-bit VC++ programs.
Related
This question already has answers here:
How to force Inno Setup setup to fail when Run command fails?
(4 answers)
Using Process Exit code to show error message for a specific File in [Run]
(2 answers)
Closed 2 years ago.
I've been creating my first installers with Inno Setup and while they work, I want to look into some more profound error handling in case things go south during installation.
Here are the script snippets containing what I have so far. All of this works, questions follow below.
[Components]
Name: "base"; Description: "Install base files needed for this application"; Types: full compact custom; Flags: fixed
Name: "fonts"; Description: "Install Spartan fonts for a correct rendering of the application"; Types: full custom
Name: "updater"; Description: "Create a scheduled task to run the component updater on a daily basis"; Types: full custom
[Tasks]
Name: "update"; Description: "Run the updater after the installation to bring all application files up to date"
[Files]
; Application files
Source: "{#MyAppSourceNetwork1}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Components: base
Source: "{#MyAppSourceNetwork1}\{#MyAppcfgName}"; DestDir: "{app}"; Flags: ignoreversion; Components: base
Source: "{#MyAppSourceNetwork1}\Source\Componenten_COM\*"; DestDir: "{app}\Componenten_COM"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: base
Source: "{#MyAppSourceNetwork1}\Source\Componenten_RegAsm\*"; DestDir: "{app}\Componenten_RegAsm"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: base
Source: "{#MyAppSourceNetwork2}\*"; DestDir: "{#MyAppLocalFolderLib}\OCXinstaller"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: base
; Updater
Source: "{#MyAppSource}\Updater\*"; DestDir: "{#MyAppLocalFolderLib}\Updater"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: base
[Run]
; Create scheduled task for updater
Filename: "powershell"; \
Parameters: "-Executionpolicy Bypass -NoProfile -WindowStyle Hidden -Command ""Register-ScheduledTask -TaskName '{#MyAppTSUpdaterName}' -Description 'Smartclient component updater' -User System -Action (New-ScheduledTaskAction -Execute wscript -Argument '{#MyAppLocalFolderLib}\Updater\{#MyAppUpdateScript}') -Trigger (New-ScheduledTaskTrigger -Daily -At 07:00) -Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Hours 2) -MultipleInstances IgnoreNew)"""; \
Description: "Create scheduled task for updater"; \
StatusMsg: "Creating scheduled task ""{#MyAppTSUpdaterName}""..."; \
Flags: runhidden; \
Components: updater
; Run scheduled task for updater
Filename: "wscript"; \
Parameters: """{#MyAppLocalFolderLib}\Updater\{#MyAppUpdateScript}"""; \
Description: "Run Smartclient component updater"; \
StatusMsg: "Running Smartclient updater. Please wait, this will take a few minutes..."; \
Flags: runhidden; \
BeforeInstall: SetMarqueeProgress(True); \
AfterInstall: SetMarqueeProgress(False); \
Tasks: update
; Offer option to launch application after installation
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent unchecked
[Code]
// Show infinite progress bar while waiting
procedure SetMarqueeProgress(Marquee: Boolean);
begin
if Marquee then
begin
WizardForm.ProgressGauge.Style := npbstMarquee;
end
else
begin
WizardForm.ProgressGauge.Style := npbstNormal;
end;
end;
For the purpose of testing, I deliberatly wrote some errors in the commands (RRRegister-ScheduledTask / UUUpdater / NNNotepad) and in the log file below, you can clearly see that the commands do not return code 0.
During the installation I got message boxes for the wscript and notepad commands, making clear that something went wrong, with the return code and an OK button. However, the Powershell command doesn't give a message at all. It only returns an error when I write the command wrong (PPPowershell.exe) but not when there is an error in the Parameters flag. Any idea why? Because I'm sure Powershell returns some nice red lines indicating an error occured.
Additionally, I notice that Inno Setup writes in the log that the installation succeeded (7th line in my snippet) although it even still needs to start with the [Run] section. When I write the commands without typos, the setup does everything correctly, but it doesn't give me much confidence in how my installers might indicate success even when some actions didn't succeed. Why isn't the [Run] block considered to be an integral part if the installation?
2020-06-10 08:52:15.025 Saving uninstall information.
2020-06-10 08:52:15.025 Deleting uninstall key left over from previous administrative 32-bit install.
2020-06-10 08:52:15.027 Creating new uninstall key: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\{C3DAA6E8-7152-40C7-8487-F4A1BDC3EB92}_is1
2020-06-10 08:52:15.027 Writing uninstall key values.
2020-06-10 08:52:15.030 Detected previous non administrative install? No
2020-06-10 08:52:15.030 Detected previous administrative 64-bit install? No
2020-06-10 08:52:15.047 Installation process succeeded.
2020-06-10 08:52:15.052 -- Run entry --
2020-06-10 08:52:15.052 Run as: Current user
2020-06-10 08:52:15.053 Type: Exec
2020-06-10 08:52:15.053 Filename: powershell
2020-06-10 08:52:15.053 Parameters: -Executionpolicy Bypass -NoProfile -WindowStyle Hidden -Command "RRRegister-ScheduledTask -TaskName 'Smartclient Updater' -Description 'Smartclient component updater' -User System -Action (New-ScheduledTaskAction -Execute wscript -Argument 'C:\Smartclient_MH_LIB\Updater\Mediahuis_Smartclient_Components_Updater.vbs') -Trigger (New-ScheduledTaskTrigger -Daily -At 07:00) -Settings (New-ScheduledTaskSettingsSet -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Hours 2) -MultipleInstances IgnoreNew)"
2020-06-10 08:52:19.509 Process exit code: 1
2020-06-10 08:52:19.511 -- Run entry --
2020-06-10 08:52:19.511 Run as: Current user
2020-06-10 08:52:19.511 Type: Exec
2020-06-10 08:52:19.511 Filename: wscript
2020-06-10 08:52:19.511 Parameters: "C:\Smartclient_MH_LIB\UUUpdater\Mediahuis_Smartclient_Components_Updater.vbs"
2020-06-10 08:57:47.994 Process exit code: 1
2020-06-10 08:57:47.996 -- Run entry --
2020-06-10 08:57:47.996 Run as: Current user
2020-06-10 08:57:47.996 Type: Exec
2020-06-10 08:57:47.996 Filename: NNNotepad
2020-06-10 08:57:47.997 Exception message:
2020-06-10 08:57:47.997 Message box (OK):
Unable to execute file:
NNNotepad
CreateProcess failed; code 2.
The system cannot find the file specified.
2020-06-10 08:57:50.009 User chose OK.
So where should I take this from here to be able to handle the return codes of these commands?
How can I specify which return codes from a [Run] line should be considered fatal, and which not? How do I catch them? I understand I will probably need to write [Code] blocks, maybe using Exec? But how do I trigger them from a [Run] line? Using Check or something else?
Can someone give an example how to catch the return code from the Powershell or Wscript command and how to throw a message box which manipulates the behaviour of the installer (e.g. quit if you click Abort, continue if you click Ignore)?
How do you manipulate the exit code from the setup itself in case things go wrong? Or is this a big no-no?
I read things about Windows process exit codes that are different than return codes in Pascal scripting. This is confusing the hell out of me. Can someone explain?
I've been looking into many examples and similar topics, but couldn't really find a useful case which I could edit to suit my needs.
Thanks for reading this far and for any help / insight you can offer.
EDIT 2020/06/16
Sorry for the delay. Meanwhile the topic has been closed, but I wanted to let you know how I solved it eventually and that I'm grateful for the help you offered. With the suggestions provided by Martin Prikryl and some additional searching I was able to reach my goals: write a [Code] block which lets me perform additional tasks, catch the return code and override the Setup exitcode if I wish to. I will post my generic code example below for anyone who needs a similar solution.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; // Example - Run additional actions purely in the [Code] block during the ssPostInstall step (executed after the [Run] block) and use ExitCode to modify the default exit code of the setup
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[Tasks]
Name: "runscript"; Description: "Run a script"
[Code]
// Start with exmpty exit code, can be used to override setup exit code with GetCustomSetupExitCode
var
ExitCode: Integer;
// Show infinite progress bar while waiting
procedure SetMarqueeProgress(Marquee: Boolean);
begin
if Marquee then
begin
WizardForm.ProgressGauge.Style := npbstMarquee;
end
else
begin
WizardForm.ProgressGauge.Style := npbstNormal;
end;
end;
// Run post-installation commands
procedure CurStepChanged(CurStep: TSetupStep);
var
ResultCode: Integer;
ProgramNAme: String;
ProgramArguments: String;
begin
if CurStep = ssPostInstall then
begin
// Change progressbar
SetMarqueeProgress(True);
// Run script if task is selected
if IsTaskSelected('runscript') then
begin
WizardForm.StatusLabel.Caption := 'Running script. This may take a few minutes...';
ProgramName := 'wscript';
ProgramArguments := ExpandConstant('{sd}\Smartclient_MH_LIB') + '\script\{#MyAppUpdateScript}';
Log('Running ' + ProgramName + ' ' + ProgramArguments);
if Exec(ProgramName, ProgramArguments, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
Log('ResultCode = ' + IntToStr(ResultCode) + '.');
if ResultCode = 0 then
begin
Log('Setup successfully ran the script.')
end
else
begin
Log('Setup failed to run the script.');
ExitCode := ExitCode + 1;
end;
end;
end
else
begin
Log('Skipping update because task "update" is not selected.');
end;
// Change progressbar
SetMarqueeProgress(False);
end;
end;
// Override setup exit code
function GetCustomSetupExitCode: Integer;
begin
if ExitCode <> 0 then
begin
Log('Returning custom exit code ' + IntToStr(ExitCode));
end;
Result := ExitCode;
end;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I have setup file for inno setup of latest version. It compiles and works great from windows xp to windows 8, but in windows 10 it fails on the moment when it creates desktop icon with next error:
IPersistFile::Save failed; code 0x80070002
This is how I create icon in setup file:
[Icons]
Name: "{userdesktop}\Forex Tester 4"; Filename: "{app}\ForexTester4.exe"; Tasks: desktopicon
Part of the installation log file:
2019-02-01 12:50:46.376 -- Icon entry --
2019-02-01 12:50:46.376 Dest filename: C:\Users\Mike\Desktop\Forex Tester 4.lnk
2019-02-01 12:50:46.376 Creating the icon.
2019-02-01 12:50:46.376 Exception message:
2019-02-01 12:50:46.376 Message box (OK):
IPersistFile::Save failed; code 0x80070002.
The system cannot find the file specified.
2019-02-01 12:50:59.066 User chose OK.
This folder exists and I can create files there manually. But inno setup fails to do this... All other icons except desktop one were created without problems.
Any ideas?
I had the same error on Windows 7 and Windows 10 because I was trying to create shortcut to file that didn't exist yet.
[Icons]
; Create icons for the app
Name: "{group}\{#AppName}"; \
Filename: "{app}\{#AppName}.lnk"; \
BeforeInstall: CreateAppRunLink();
Name: "{commondesktop}\{#AppName}"; \
Filename: "{app}\{#AppName}.lnk"; \
Tasks: desktopicon;
So I had to make sure that file "{app}{#AppName}.lnk" exists prior to creating the Icon:
This goes to [Code] section:
procedure CreateAppRunLink();
var
Filename: string;
Description: string;
ShortcutTo: string;
Parameters: string;
WorkingDir: string;
IconFilename: string;
begin
Filename := ExpandConstant('{app}\MyApp.lnk');
Description := 'Description';
ShortcutTo := 'Full path to file that will be run (MyApp.exe)';
Parameters := 'parameters if any';
WorkingDir := ExpandConstant('{app}');
IconFilename := ExpandConstant('{app}') + '\icon.ico';
CreateShellLink(Filename, Description, ShortcutTo, Parameters, WorkingDir,
IconFilename, 0, SW_HIDE);
end;
CreateAppRunLink will will be called after extracting any files from [Files] section which will make sure that our file is in place.
Hope that'll help.
It could be a relatively new (since version 1709) Windows 10 feature called Controlled folder access. See Allow a blocked app in Windows Security for instructions on turning it on or off.
My InnoSetup script opens a web page (with the user's default browser) at the end of the install process:
[Run]
Filename: http://example.com; Flags: shellexec
However, I'd like the web page to not be opened if the app already exists, i.e., if the user is installing a new version of the program. The web page should only be opened after the initial install. (I assume it's worth mentioning that the install includes an AppID, obviously, and enters values in the registry beside installing files.)
Thank you, as always -- Al C.
Yes, this is easy to do with scripting.
Just write
[Run]
Filename: "http://example.com"; Flags: shellexec; Check: NotAnUpdate
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpInstalling then
IsUpdate := FileExists(ExpandConstant('{app}\TheFileNameOfMyApp.exe'));
end;
function NotAnUpdate: Boolean;
begin
result := not IsUpdate;
end;
The answer by #AndreasRejbrand won't work, if user chooses to install the executable to a different location than the last time.
You can query installer-specific Inno Setup registry keys:
#define AppId "your-app-id"
#define SetupReg \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppId + "_is1"
#define SetupAppPathReg "Inno Setup: App Path"
[Setup]
AppId={#AppId}
...
[Run]
Filename: "https://www.example.com/"; Flags: shellexec; Check: not IsUpgrade
...
[Code]
function IsUpgrade: Boolean;
var
S: string;
begin
Result :=
RegQueryStringValue(HKLM, '{#SetupReg}', '{#SetupAppPathReg}', S) or
RegQueryStringValue(HKCU, '{#SetupReg}', '{#SetupAppPathReg}', S);
end;
For an example how to use IsUpgrade in [Code] section, see
Excludes part of Code section in ssPostInstall step if installation is update in Inno Setup
Check this if your "AppId" contains a left-curly-bracket:
Checking if installation is fresh or upgrade does not work when AppId contains a curly bracket
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
My InnoSetup script opens a web page (with the user's default browser) at the end of the install process:
[Run]
Filename: http://example.com; Flags: shellexec
However, I'd like the web page to not be opened if the app already exists, i.e., if the user is installing a new version of the program. The web page should only be opened after the initial install. (I assume it's worth mentioning that the install includes an AppID, obviously, and enters values in the registry beside installing files.)
Thank you, as always -- Al C.
Yes, this is easy to do with scripting.
Just write
[Run]
Filename: "http://example.com"; Flags: shellexec; Check: NotAnUpdate
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpInstalling then
IsUpdate := FileExists(ExpandConstant('{app}\TheFileNameOfMyApp.exe'));
end;
function NotAnUpdate: Boolean;
begin
result := not IsUpdate;
end;
The answer by #AndreasRejbrand won't work, if user chooses to install the executable to a different location than the last time.
You can query installer-specific Inno Setup registry keys:
#define AppId "your-app-id"
#define SetupReg \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppId + "_is1"
#define SetupAppPathReg "Inno Setup: App Path"
[Setup]
AppId={#AppId}
...
[Run]
Filename: "https://www.example.com/"; Flags: shellexec; Check: not IsUpgrade
...
[Code]
function IsUpgrade: Boolean;
var
S: string;
begin
Result :=
RegQueryStringValue(HKLM, '{#SetupReg}', '{#SetupAppPathReg}', S) or
RegQueryStringValue(HKCU, '{#SetupReg}', '{#SetupAppPathReg}', S);
end;
For an example how to use IsUpgrade in [Code] section, see
Excludes part of Code section in ssPostInstall step if installation is update in Inno Setup
Check this if your "AppId" contains a left-curly-bracket:
Checking if installation is fresh or upgrade does not work when AppId contains a curly bracket