How Get Full Name From Paramaters {app} for one string [duplicate] - inno-setup

I'm trying to create a setup with Inno Setup.
In the run section, I want to launch a bat with two parameters but in the first parameters, there is a path file and a space is potentially inside. How to avoid the problem?
I found this topic in vain...
Inno Setup, spaces and double quote in [Run]
Thanks for your help.
[Run]
Filename: {code:GetDirSQL|0}\installSQL\createBase\launchCreateParam.bat;
Parameters: {code:GetDirSQL|0}\installSQL\createBase {code:GetDossier|0};
Description: {cm:LaunchProgram,LumisTraiteur};
StatusMsg: Création de la base de données...; Check: instalDossier

See Parameters in Sections:
Parameters: """{code:GetDirSQL|0}\installSQL\createBase"" ""{code:GetDossier|0}"""
It may get more complicated, when the application, you are running, treats the quotes and spaces specially:
How to handle path with spaces in Inno Setup?
Inno Setup, spaces and double quote in [Run]

Related

Can Inno Setup Preprocessor be used to build a duplicated set of custom messages?

My installer caters for 20 partial translations. Partial translations have the bulk of the GUI in English and just certain parts in the respective languages. To acheive this with the installer I physically duplicate the default English isl file and rename the language name property to each of the twenty languages. Then Iuse those files in the installer script to add these languages to the drop-down list for the user to choose from.
What this means is that for my custom message I have to replicate them for each of the 20 languages. At the moment I am doing it manually but I wondered if this can be managed from now on using ISPP?
So we start with these custom messages:
; Automatic Backup Settings Wizard Page
English.pageAutoBackupTitle=Automatic Backup
English.pageAutoBackupDescription=Configure automatic backup settings.
English.lblBackupWhat=What to backup:
English.radBackupWhatNone=Don't perform any backup when the program shuts down
English.radBackupWhatComplete=Make a complete backup when the program shuts down
English.radBackupWhatEssential=Only make an essential backup when the program shuts down
English.lblBackupMode=How to backup:
English.radBackupModeAuto=Perform automatically when the program is shut down
English.radBackupModeManual=Prompt the user when the program is shut down
English.lblPromptMode=Also prompt to backup at the following intervals while the application is running:
English.cmbPromptModeItemNever=Never prompt to backup
English.cmbPromptModeItemDaily=Prompt to backup everyday
English.cmbPromptModeItemWeekly=Prompt to backup once a week
English.cmbPromptModeItemMonthly=Prompt to backup once a month
English.lblBackupFolder=Where to backup:
English.btnButtonBrowse=Browse ...
And we want to replicate them for the following languages identifiers:
Amharic
Aukan
Cebuano
Filipino
Gujarati
Gun
HaitianCreole
Lingala
Malagasy
Maltese
Punjabi
Saramaccan
Sesotho
Setswana
Sranantongo
Swahili
Tamil
Tsonga
Twi
Zulu
I know I don't need to add the custom messages because the installer would default to English, but then I get the barage of compiler warnings about missing message definitions.
The preprocessor has two mechanisms how to repeat some code, both having advantages and disadvantages.
User defined procedures
With the User defined procedures, the code that you want to repeat is a way more readable – you basically use the same syntax as if you write a normal script (even syntax highlighting will work in editors), you just use {#Var} syntax to inject the variable parts.
There's virtually no limit to how long the repeated code can be long.
But the code to cause the code to repeat is clumsier, as the procedures cannot take arguments, so you have to pass the variable parts via "global variables". But in your case, with a single parameter and no recursion, it's not a big limitation.
#sub DefaultMessages
{#Lang}.pageAutoBackupTitle=Automatic Backup
{#Lang}.pageAutoBackupDescription=Configure automatic backup settings.
{#Lang}.lblBackupWhat=What to backup:
; ...
#endsub
#define Lang
#expr Lang = "German"
#expr DefaultMessages
#expr Lang = "French"
#expr DefaultMessages
; ...
If you prefer, you can put the variable assignment and procedure call to the same line using a sequential evaluation operator (a comma):
#define Lang
#expr Lang = "German", DefaultMessages
#expr Lang = "French", DefaultMessages
; ...
User defined functions
User defined functions can take parameters, so from a programming perspective, they are cleaner – and allow a recursion (not relevant in this case).
But the code is not very readable. And there's an internal preprocessor stack limit, which makes the solution not scalable.
#define DefaultMessages(Lang) \
Lang + ".pageAutoBackupTitle=Automatic Backup" + NewLine + \
Lang + ".pageAutoBackupDescription=Configure automatic backup settings." + NewLine + \
Lang + ".lblBackupWhat=What to backup:" + NewLine \
; ...
#emit DefaultMessages("German")
#emit DefaultMessages("French")
; ...
For another example, that shows implementing the same functionality using both these approaches, see:
Inno Setup - Recurse sub directories without creating those same sub directories
I am adding this answer just so that users are aware of a better approach to my situation.
I was recently told this (quite by chance as my question was a different one) on the Inno Setup Support channel:
It loads the MessageFiles in order, followed by the messages in the
script. Last one wins.
And prefixed values win over un-prefixed values within the script as
well.
So you should put all your English defaults into an .isl file that is
listed before the language-specific .isl file. Anything not specified
in the real language file will use the defaults from the previous
files.
Or alternatively if you do not want to use .isl files for your custom
messages, then you can specify your English defaults without prefix
and your actual translations with the appropriate prefix directly in
your script, omitting anything not yet translated. Again, anything
that's missing a language-specific-prefixed value will default back
to the un-prefixed value.
If you do both things, then anything in the script (prefixed or not)
will always override anything in the .isl files.
So I simplified my custom messages file:
[CustomMessages]
; ==================================================================
; These are the default custom messages.
; They are used by:
; - Amharic
; - Aukan
; - Cebuano
; - English
; - Filipino
; - Gujarati
; - Gun
; - HaitianCreole
; - Lingala
; - Malagasy
; - Maltese
; - Punjabi
; - Saramaccan
; - Sesotho
; - Setswana
; - Sranantongo
; - Swahili
; - Tamil
; - Tsonga
; - Twi
; - Vietnamese
; - Zulu
pageAutoBackupTitle=Automatic Backup
pageAutoBackupDescription=Configure automatic backup settings.
lblBackupWhat=What to backup:
radBackupWhatNone=Don't perform any backup when the program shuts down
radBackupWhatComplete=Make a complete backup when the program shuts down
radBackupWhatEssential=Only make an essential backup when the program shuts down
lblBackupMode=How to backup:
radBackupModeAuto=Perform automatically when the program is shut down
radBackupModeManual=Prompt the user when the program is shut down
lblPromptMode=Also prompt to backup at the following intervals while the application is running:
cmbPromptModeItemNever=Never prompt to backup
cmbPromptModeItemDaily=Prompt to backup everyday
cmbPromptModeItemWeekly=Prompt to backup once a week
cmbPromptModeItemMonthly=Prompt to backup once a month
lblBackupFolder=Where to backup:
All language prefixed translations follow in the same file. Using this approach I don't actually need to use the #sub / #endsub mechanism after-all.

Inno Setup setup file name append AppVersion

How to append AppVersion to setup.exe file?
In other words, how to make output filename as sample-setup-1.4.2.0.exe?
[Setup]
AppName= {#GetStringFileInfo("Sample.exe", "ProductName")}
AppVersion= {#GetStringFileInfo("Sample.exe", "FileVersion")}
OutputBaseFilename=setup
Two valuable lessons are;
Lesson 1: Inline function should be used as {#FunctionName(...)}
Lesson 2: variables in [Setup] field are called by using SetupSetting function.
With above information, we can make sample-setup-1.0.0.0 as below;
OutputBaseFilename=sample-setup-{#SetupSetting("AppVersion")}
Likewise, we can append datetime;
OutputBaseFilename=sample-setup-{#SetupSetting("AppVersion") + GetDateTimeString('dd-mm-yyyy hh-nn-ss', '-', ':')}

Inno Setup Delete method not working as expected

I have an application version that includes a hash. For sake of the installer, I want a simple version without the hash. I have the following code which mostly works, the part in question is the Delete call which according to the documentation Deletes the specified number of characters beginning with Index from S. S is passed by reference (therefore is modified).
#define FullAppVersion "0.0.9 - abcdef012345"
#expr WriteIni("D:\\debug.txt", "Debug", "Full", FullAppVersion)
#define SimpleVersion FullAppVersion
#expr WriteIni("D:\\debug.txt", "Debug", "SimpleBefore", SimpleVersion)
#define HashPos Pos(' ', SimpleVersion)
#expr WriteIni("D:\\debug.txt", "Debug", "Pos", HashPos)
#expr Delete(SimpleVersion, HashPos)
#expr WriteIni("D:\\debug.txt", "Debug", "SimpleAfter", SimpleVersion)
However, when the above is executed, the debug looks as such:
[Debug]
Full=0.0.9 - abcdef012345
SimpleBefore=0.0.9 - abcdef012345
Pos=6
SimpleAfter=0.0.90.0.9 - abcdef012345
Delete seems to partially work by trimming from the specified position, but then additionally concatenates the entire string at the end.
Am I doing something incorrectly, or is there a glitch in the function? Using Inno Setup Compiler 5.5.5 and Inno Script Studio 2.2.1.31

How to test if a windows group exists from inno setup?

How can you test to see if a windows group is already setup? Can you somehow use the response from:
Exec('net.exe', 'localgroup', '', SW_SHOW, ewWaitUntilTerminated, Result);
which will list the groups to the command prompt? (I know that Result is an error code where 0 is success, just to be clear.)
Is there a way? Is there more than one way?
I haven't tested this, or had time to work out the exact process or syntax, but you could possibly use command redirection (see https://technet.microsoft.com/en-us/library/bb490982.aspx), using net localgroup as you suggested, to find the group name and output it to a text file. You could then read it into Inno Setup using LoadStringFromFile, then all you would need to do is compare the two strings.
So, having looked at this in more detail, to see if the Administrators group exists you could use:
[Run]
Filename: "{cmd}"; Parameters: "/c ""net localgroup | find /i ""Administrators"" > ""{tmp}\groupresult.txt"""""; StatusMsg: "Querying user groups..."; Flags: runhidden
[Code]
var
strGroupResult: String;
begin
LoadStringFromFile(ExpandConstant('{tmp}\groupresult.txt'), strGroupResult);
if strGroupResult = '*Administrators' then
begin
//Code to execute if group exists
...
end;
DeleteFile(ExpandConstant('{tmp}\groupresult.txt'));
end;
Note that net localgroup returns an asterisk (*) in front of the group name, so the string comparison needs to also include the asterisk.
If you need to do this before the [Run] section, you can write a similar Exec line in the [Code] section to run the same process.

How to access texts from language files from the code section?

In Inno Setup one can access texts from the language files e.g. the following way (where CreateDesktopIcon is the text entry to look for):
[Tasks]
Name: "TaskDesktopIcon"; Description: "{cm:CreateDesktopIcon}"; Flags:
My question is how to access texts from the language files from the code section of the Inno Setup script?
I have tried the following, but the compiler will not accept the syntax:
[code]
var
pageAutoLogon: TWizardPage;
procedure CreateAutoLogonPage;
begin
pageAutoLogon := CreateCustomPage(wpSelectTasks, "{cm:AutoLogonCredentialsTitle}", "{cm:AutoLogonCredentialsDescription}");
...
Any help is appreciated!
You need to call ExpandConstant (or ExpandConstantEx) function to evaluate a constant in script code. Like this way for instance:
procedure CreateAutoLogonPage;
begin
pageAutoLogon := CreateCustomPage(wpSelectTasks, ExpandConstant('{cm:AutoLogonCredentialsTitle}'), ExpandConstant('{cm:AutoLogonCredentialsDescription}'));
...
end;
You can use the CustomMessage() function to retrieve the values from the [CustomMessages] section.
pageAutoLogon := CreateCustomPage(wpSelectTasks, CustomMessage('AutoLogonCredentialsTitle'), CustomMessage('AutoLogonCredentialsDescription'));
For normal [Messages], you can use the SetupMessage() with one of the enum values.

Resources