Inno Setup - How to execute MSI between 32 and 64 architectures - inno-setup

im trying to run 2 msi files for 32 and 64 bits from a third party and i am having a little trouble with the msi for 32bits windows architectures.
It seems the program extracts quite well the file but it doesn´t execute the installer. In the other hand for 64bits windows architectures the installer works. I don´t know where is the problem. Is there anything wrong with my code that im not seeing?Thank you!
[Setup]
...
ArchitecturesInstallIn64BitMode=x64
[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "filex64.msi"; DestName: "file.msi"; DestDir: "{app}"; Flags: deleteafterinstall; Check: Is64BitInstallMode
Source: "filex32.msi"; DestName: "file.msi"; DestDir: "{app}"; Flags: deleteafterinstall; Check: not Is64BitInstallMode;
Source: "manual.pdf"; DestDir: "{userdesktop}"; DestName: "Manual.pdf"
[Run]
Filename: "{sys}\msiexec.exe"; Parameters: "/package ""{app}\file.msi"" /qn /norestart /passive"; Flags: shellexec waituntilterminated; StatusMsg: "A instalar software {#MyAppVersion}";
Filename: "{userdesktop}\Manual.pdf"; Flags: postinstall;

I figure it out.
Flags
32bit
Causes the {sys} constant to map to the 32-bit System directory when used in the Filename and WorkingDir parameters. This is the default behavior in a 32-bit mode install.
This flag cannot be combined with the shellexec flag.
64bit
Causes the {sys} constant to map to the 64-bit System directory when used in the Filename and WorkingDir parameters. This is the default behavior in a 64-bit mode install.
This flag can only be used when Setup is running on 64-bit Windows, otherwise an error will occur. On an installation supporting both 32- and 64-bit architectures, it is possible to avoid the error by adding a Check: IsWin64 parameter, which will cause the entry to be silently skipped when running on 32-bit Windows.
This flag cannot be combined with the shellexec flag.
Source:
http://www.jrsoftware.org/ishelp/index.php?topic=isxfunc_iswin64
Based on this, i changed my script ir order to pinpoint correctly the "msiexec.exe" file for both architectures. Thank you guys!
[Run]
Filename: "{sys}\msiexec.exe"; Parameters: "/package ""{userdesktop}\Classic_Client_{#MyAppVersion}_64.msi"" /qn /norestart /passive"; Flags: 64bit skipifdoesntexist waituntilterminated; Check:IsWin64; StatusMsg: "A instalar Classic Client {#MyAppVersion} - 64bit";
Filename: "{sys}\msiexec.exe"; Parameters: "/package ""{userdesktop}\Classic_Client_{#MyAppVersion}_32.msi"" /qn /norestart /passive"; Flags: 32bit skipifdoesntexist waituntilterminated; StatusMsg: "A instalar Classic Client {#MyAppVersion} - 32bit";

the {sys} constant is the issue.
{sys} The system's System32 directory. For example: If you used
{sys}\CTL3D32.DLL on an entry and the system's Windows System
directory is "C:\WINDOWS\SYSTEM", Setup or Uninstall will translate it
to "C:\WINDOWS\SYSTEM\CTL3D32.DLL".
On 64-bit Windows, by default, the System32 path returned by this
constant maps to the directory containing 32-bit system files, just
like on 32-bit Windows. (This can be overridden by enabling 64-bit
mode.)

Related

Inno Setup is unable to install to LocalSystem's %LOCALAPPDATA%

I have a Windows service that runs as the local system account. It stores some data in its %LOCALAPPDATA% folder. For LocalSystem, this is the following location:
C:\Windows\system32\config\systemprofile\AppData\Local
This works without a hitch; the service creates its own subfolder and writes files to it.
Now, using Inno Setup, I'm trying to install an initial file to that folder:
[Files]
Source: "LICENSE"; DestDir: "{sys}\config\systemprofile\AppData\Local\InnoTest"; Flags: ignoreversion
The log suggests that this works fine:
[14:20:10,722] -- File entry --
[14:20:10,725] Dest filename: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest\LICENSE
[14:20:10,729] Time stamp of our file: 2022-10-24 13:56:42.000
[14:20:10,731] Installing the file.
[14:20:10,734] Creating directory: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest
[14:20:10,738] Successfully installed the file.
It says "successfully installed the file", but neither the file nor the directory is anywhere to be seen.
Run the installer again, however, and you will be told that the destination file exists:
[14:24:47,381] -- File entry --
[14:24:47,395] Dest filename: C:\Windows\system32\config\systemprofile\AppData\Local\InnoTest\LICENSE
[14:24:47,398] Time stamp of our file: 2022-10-24 13:56:42.000
[14:24:47,400] Dest file exists.
[14:24:47,403] Time stamp of existing file: 2022-10-24 13:56:42.000
[14:24:47,405] Installing the file.
[14:24:47,410] Successfully installed the file.
So: The installer thinks the file exists, but I can't see it.
This is specifically an issue with the System account; if I switch to, say, the %LOCALAPPDATA% of the LocalService account, things work as expected:
[Files]
Source: "LICENSE"; DestDir: "{win}\ServiceProfiles\LocalService\AppData\Local\InnoTest"; Flags: ignoreversion
If anyone could shed some light on what is (or isn't) going on here, it would be much appreciated.
Minimal, reproducible and complete example here.
This is almost a duplicate of:
File/DLL installed to {sys} does not appear in C:\Windows\system32
Though your question probably deserves specific answer.
If I understand correctly, you want to install to System32 on both 32-bit and 64-bit systems. So there are two options:
Use the 64-bit mode;
If you do not want (or not dare) to switch whole installer to 64-bit mode, you will need two entries in the [Files] section. One for 64-bit systems with 64bit flag and one for 32-bit systems without the flag:
[Files]
Source: "LICENSE"; \
DestDir: "{sys}\config\systemprofile\AppData\Local\InnoTest"; \
Flags: ignoreversion; Flags: 64bit; Check: IsWin64
Source: "LICENSE"; \
DestDir: "{sys}\config\systemprofile\AppData\Local\InnoTest"; \
Flags: ignoreversion; Check: not IsWin64

How to find installed directory in inno setup?

I have created an installer using innosetup. Where User can choose the directory where he wants to install by setting up DisableDirPage=No but when it comes to patch installers it is failed to update as user has been installed the app to his preferred directory. How to make installer to identify in which directory the app has been installed and make the patch installer to work.
installer code:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
Compression=lzma2
SolidCompression=yes
OutputDir = c:\test
OutputBaseFilename=update
DisableDirPage=No
[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"
Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme
[Icons]
Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"
If I unterstand you correctly you are talking about the setuo for your own application. You can put the UsePreviousAppDir directive in your [Setup] section. It's not necessary because its default value is 'yes' anyway. The documentation (http://jrsoftware.org/ishelp/) says that the Setup is looking for the same application, which is defined by the AppId or the AppName.
As long as you use AppName=My Program like in your example code, Inno Setup should find the install path of the old version itself. But if the AppName or AppId changes in your new version, there is no way to find it in the registry. A changing AppId is likely if you use a new guid for every setup.

Run inno setup from shared drive

I have created a inno setup installer for my application. Now I want to place that installer on a shared folder where the users can install from there.
The installer need to place the files on the {%HOMEPATH}\{#MyAppName}directory. But when I set the AllowUNCPath=yes it can be ran from the shared drive but it will install the files on the fileshare\{%HOMEPATH}\{#MyAppName}.
Is it possible to run the installer from the fileshare and install it on the user local drive?
My setup section looks like:
[Setup]
AppId="{{AAAAAA-AAAA-AAAA-AAAA-AAAAAAAA}"
AppName={#MyAppName}
;AppVersion={#MyAppVersion}
AppVersion={code:getVersionNumber}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={%HOMEPATH}\{#MyAppName}
DefaultGroupName={#MyAppPublisher}
OutputDir=compiledInstaller
OutputBaseFilename=setup
SetupIconFile={#iconName}
;Set some installer settings
Compression=lzma
SolidCompression=yes
ArchitecturesAllowed=x64
PrivilegesRequired=lowest
AllowCancelDuringInstall=False
AllowUNCPath=false
ArchitecturesInstallIn64BitMode=x64
CreateUninstallRegKey=yes
UsePreviousAppDir=yes
;Disable different screens
DisableDirPage=yes
DisableProgramGroupPage=yes
DisableReadyPage=True
DisableReadyMemo=True
DisableFinishedPage=True
DisableWelcomePage=True
[Files]
Source: "{#path}*"; DestDir: "{app}"; Flags: external recursesubdirs
Source: "{#path}/.eclipseproduct"; DestDir: "{app}"; Flags: external
Source: "{#installerPath}/{#ScriptName}"; DestDir: "{app}"; Flags: external
Source: "{#installerPath}/{#iconName}"; DestDir: "{app}"; Flags: external
The path and installerPath variables are linked to the files on the shared drive.
The error that I got when running the installer from the shared drive looks like:
Your problem has nothing to do with a shared drive.
It's due to the HOMEPATH variable. Its value is like \Users\username. There's no drive in the path. So it can only ever work, if you run the installer from the C: drive. If you run it from anywhere else, the path is naturally resolved incorrectly.
You have to use an absolute path. You can use USERPROFILE variable instead of HOMEPATH. The USERPROFILE value is like C:\Users\username.

Kill process before (re)install using "taskkill /f /im" in Inno Setup

I install a service/daemon, which needs to be killed before uninstall and reinstall.
I already found out how to do it for uninstall:
[UninstallRun]
Filename: "taskkill"; Parameters: "/im ""My Service.exe"" /f"; Flags: runhidden
The [Run] section, however, runs after install, so I can't use it for that. What is the best way to kill the process using taskkill before install?
Please note that I specifically want to kill the process. A more complex solution using IPC offers no benefits in my case, I just want to execute taskkill before installing a particular file.
I found a way using the BeforeInstall parameter and a simple Pascal Script function in the code section. I added a string parameter so it can be reused for multiple processes.
[Files]
Source: "My Service 1.exe"; DestDir: "{app}"; Flags: ignoreversion; \
BeforeInstall: TaskKill('My Service 1.exe')
Source: "My Service 2.exe"; DestDir: "{app}"; Flags: ignoreversion; \
BeforeInstall: TaskKill('My Service 2.exe')
[Code]
procedure TaskKill(FileName: String);
var
ResultCode: Integer;
begin
Exec('taskkill.exe', '/f /im ' + '"' + FileName + '"', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode);
end;
Unless the installer needs to run on a Windows XP machine, or you have set CloseApplications directive to no (the default is yes), the installer should close the application automatically:
The functionality is available since Inno Setup 5.5 on Windows Vista and newer.
Though sometimes yes is not enough, you need to use force:
Installer created via Inno Setup, can't close applications during installation on Windows 10

how to detect 64bit platform by script

is there code to detect 64 platform e.g.
if X86 then ...
if X64 then ...
If you want to throw a check on whether to drop or run a file you can also throw a check on the call.
Check: IsWin64;
or even
Check: "not IsWin64";
This allows a quick and easy way to compile 32-bit & 64-bit application installers into one package, but only run the specific one.
EDIT: To expand a little further for those that might be searching for this, I wanted to follow up.
For example, if you want to only allow certain files to be copied down by the installer you could do the following:
[Files]
Source: "MyProg-x64.exe"; DestDir: "{app}"; Check: IsWin64;
Source: "MyProg-x86.exe"; DestDir: "{app}"; Check: "not IsWin64";
Adapted from source: http://www.jrsoftware.org/ishelp/index.php?topic=scriptcheck
Yes.
Use
if IsWin64 then
// Do sth
else
// Do sth else
There is also a Is64BitInstallMode function. Indeed, a 32-bit setup can run on a 64-bit OS. Hence, Is64BitInstallMode implies IsWin64, but IsWin64 does not imply Is64BitInstallMode.

Resources