Constant defined using Inno Setup preprocessor #define is not recognised in ExpandConstant - inno-setup

I'm trying to set up an install file that (optionally) installs .NET 5 if it's not already installed.
However, I'm having trouble defining the version of .NET to install in a constant.
My script is set up like this
#define DotNetVersion "5"
...
[Tasks]
Name: "dotnet"; Description: "{cm:DotNet}"; GroupDescription: "{cm:Prerequisites}"
...
[Files]
Source: "..\Dependencies\{#DotNetInstallFile}"; DestDir: {tmp}; \
Flags: deleteafterinstall; AfterInstall: InstallDotNet; \
Check: NetNotInstalled(ExpandConstant('{DotNetVersion}')); Tasks: "dotnet"
When I try running the resulting install file I get the following error:
Internal error: Expression error 'Internal error: Unknown constant "DotNetVersion"'
The function NetNotInstalled works correctly if I replace ExpandConstant('{DotNetVersion}') with '5', but I want to easily be able to change this without modifying more than the defined constants.
I don't get what's wrong here. The Inno Setup docs state that this should be valid.
Using the same constant for any other function seems to work flawlessly.

A variable defined using Inno Setup preprocessor is not Inno Setup constant. Calling ExpandConstant function on it has no effect.
To expand preprocessor variable (or any expression), you can use {#VariableOrExpression} syntax. It's an inline preprocessor directive call, where, when no directive is explicitly specified, the emit is implied. So the {#VariableOrExpression} is the same as {#emit VariableOrExpression}. And as every preprocessor construct, it's evaluated on compile time (contrary to ExpandConstant).
You actually do that correctly already with {#DotNetInstallFile}, so do the same with DotNetVersion:
Source: "..\Dependencies\{#DotNetInstallFile}"; \
DestDir: {tmp}; Flags: deleteafterinstall; AfterInstall: InstallDotNet; \
Check: NetNotInstalled('{#DotNetVersion}'); Tasks: "dotnet"
See also How to use variables \ macros with Inno Setup?

Related

Elegantly using try / catch with dotnet constants in Inno [Run] section [duplicate]

I have a .NET DLL. It can be registered by RegAsm .NET 3.5 and .NET 4.5.
I use this codes in my setup script:
[Run]
Filename: "{dotnet40}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet4064}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet20}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet2064}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
It works well if .NET 3.5 and .NET 4.5 is installed on the target machine
I have a function in my script to checking .net in InitializeSetup. So I know one of these versions are installed on the system: v3.5 v4 v4.5
But
we get error in some cases like this: if we have not .NET 3.5 on the target machine
I guess the error reason is:
{dotnet20}
.NET Framework version 2.0 root directory. {dotnet20} is equivalent to {dotnet2032} unless the install is running in 64-bit
mode, in which case it is equivalent to {dotnet2064}.
An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 2.0 present.
My question is how can I handle and ignore this exception and prevent setup rollback:
Internal error: .Net Framework version 2.0 not found.
If you want to stick to the [Run] section and do not write this in a scripting code, then I think you don't have many options to choose from. An exception is raised whenever a constant cannot be expanded, and that is just this case. The only option I can think of is adding a Check function that will attempt to expand the constant in a protected try..except block and prevent the entry to be processed when an exception is raised. Something like follows (based on your code, shortened):
[Run]
Filename: "{dotnet20}\RegAsm.exe"; Parameters: "File.dll"; Check: RegAsmDotNet20Exists
[Code]
function RegAsmDotNet20Exists: Boolean;
begin
try
// process the entry only if the target binary could be found (and so the
// folder constant could have been properly expanded)
Result := FileExists(ExpandConstant('{dotnet20}\RegAsm.exe'));
except
// this is the fallback in case the folder constant could not be expanded,
// or something unexpected happened when checking if the binary file to be
// executed exists; in such case, don't process the entry
Result := False;
end;
end;
Another, quite cleaner and a bit safer option would be doing your assembly registration purely from [Code] section in some of the postinstall events. Even though you'd still need to catch exceptions when using those constants, you would get more control over that tool (e.g. you could get the exit code to obtain an error reason if that tool uses it).

How to control addition of file in Inno Setup 6 script using the presence of a substring in a defined string

I have two executables which do the same thing, but one is built to target a DEV environment, and the other a PROD environment.
my-app-dev.exe
my-app-prod.exe
A VERSION parameter is always passed into the Inno build script which contains the build version in one of the following two formats:
"1.0.0"
"1.0.0-DEV"
In the [Files] section, how can I include the my-app-dev.exe if the current value of VERSION contains the DEV suffix, but include the my-app-prod.exe if not?
I figured a Check parameter would be the way to resolve this, but I can't even get the simplest case to work.
For example, the following adds the file to the build despite the Check function clearly returning False.
[Files]
Source: "my-app-dev.exe"; DestDir: {app}; Check: ShouldIncludeDev
function ShouldIncludeDev: Boolean;
begin
Result := False;
end;
Perhaps I must be missing something fundamental here...
Based on this answer (Inno Setup IDE and ISCC/ISPP passing define) you could do this:
Pass the value via command line parameter:
/DargDEV="DEV"
In your [Files] section you can then do this:
#ifdef argDEV
Source: "my-app-dev.exe"; DestDir: {app};
#else
Source: "my-app-prod.exe"; DestDir: {app};
#endif
Notes
It uses the #ifdef pre-processor directive.

Read destination directory from ini file during install time in Inno Setup

I need to read a directory path from an ini file at install time.
Under the [Code] section I have defined a function like
function GetDirectoryFromIni: String;
begin
Result :=
GetIniString('Directories' , 'Name' ,
ExpandConstant('{app}')+'\Default_Path\' ,
ExpandConstant('{app}')+'my_ini_file.ini');
end;
How can I use this function/path/string in the [Files] section?
Something like:
[Files]
Source: "C:\Source_Directory\*.*"; DestDir: "GetDirectoryFromIni"; \
Flags: ignoreversion
The basic logic is if the user has changed the "Default_Path" from a previous installation I want to adjust to use it, otherwise it uses the default path when the program is first installed.
I cannot seem to define or set a string variable to use the GetDirectoryFromIni result. Can anyone help?
You can do this even without any Pascal Script code. There's {ini} "constant":
[Files]
Source: "C:\Source_Directory\*.*"; \
DestDir: "{ini:{app}\my_ini_file.ini,Directories,Name|{app}\Default_Path\}"; \
Flags: ignoreversion
For an answer for your expected solution, see:
Using global string script variable in Run or other section in Inno Setup
You need to refer to the function in the [Files] section like
[Files]
Source: "C:\Source_Directory\*.*"; DestDir: "{code:GetDirectoryFromIni}"; Flags: ignoreversion
Then it works.

Inno Setup constants and parameters [duplicate]

This question already has answers here:
Passing in version number to Inno Setup compiler
(3 answers)
Closed 2 years ago.
I'm trying to add a parameter to my setup file, with a default value.
In this case I get a compile error at
OutputBaseFilename=MyApp {param:Version|{#MyAppVersion}} Setup
Saying:
Value of [Setup] section directive "OutputBaseFilename" is invalid
Shortened reference code:
#define MyAppName "My App"
#define MyAppVersion "1.7.24"
[Setup]
AppName={#MyAppName}
AppVersion="{param:Version|{#MyAppVersion}}"
DefaultGroupName=VHStudio
OutputBaseFilename=MyApp {param:Version|{#MyAppVersion}} Setup
SetupIconFile={#PathToRepoRoot}\Development\VHS\VHSStudio\media\logo.ico
[Icons]
Name: "{group}\VHStudio {param:version|MyAppVersion}"; Filename: "{app}\VHStudioApp.EXE"; WorkingDir: "{app}"
Name: "{group}\Uninstall VHStudio"; Filename: "{app}\unins000.exe"; WorkingDir: "{app}"
Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\VHStudioApp.EXE"; Tasks: desktopicon
I'm guessing I'm using the constant wrong?
The Strange thing is that I do
AppVersion="{param:Version|{#MyAppVersion}}"
Without any errors...
Based on the comment from Martin. Suggesting to take a look at Passing in version number to Inno Setup compiler.
Turns out I overcomplicated things. You can easily pass parameters to the compiler for pre-processor variables. In my situation MyAppVersion.
What I did in Inno Setup:
#ifndef MyAppVersion
#define MyAppVersion "1.7.24"
#endif
And when compiling it looks like this:
ISCC.exe myProg.iss /DMyAppVersion=1.7.14

Inno Setup "Wrong Parameter" (Wusa.exe and .msu)

I am trying to create a Setup using Inno Setup. Because I have to install a .msu file, I use the Wusa.exe.
The important code line:
Filename: {sys}\wusa.exe; WorkingDir: {app}; Parameters: {app}\Windows6.1-KB2506143-x64.msu;
Every time I launch the program, it gives me this error and I couldn't figure out a solution yet:
2147942487 "Wrong Parameter."(Commandline:""C:\Windows\system32\wusa.exe" C:\Program Files (x86)\Phone-O-Mat\Windows6.1-KB2506143-x64.msu")
You are missing quotes around the file name. You need these, as the {app} resolves to a path with spaces:
Filename: {sys}\wusa.exe; WorkingDir: {app}; \
Parameters: """{app}\Windows6.1-KB2506143-x64.msu"""

Resources