Change the setup language while setup is running (Inno Setup) - inno-setup

How to add the choice of language to the first page, as it is shown in the video?
http://screencast.com/t/SDI5VN67LFL
Thank you all in advance for your help.

Based on the code in this answer, it does what you wanted:
[Setup]
DisableWelcomePage=False
ShowLanguageDialog=no
{...}
[Languages]
Name: "English"; MessagesFile: "compiler:Default.isl"
Name: "French"; MessagesFile: "compiler:Languages\French.isl"
Name: "German"; MessagesFile: "compiler:Languages\German.isl"
Name: "Spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
//Add languages as you like ...
{...}
[Code]
var
LangCombo: TNewComboBox;
SelectLangLabel: TNewStaticText;
LangArray: Array of String;
IsConfirm: Boolean;
function ShellExecute(hwnd: HWND; lpOperation, lpFile, lpParameters, lpDirectory: String; nShowCmd: Integer): THandle;
external 'ShellExecuteW#shell32.dll stdcall';
function IsSetLang: Boolean;
begin
Result := (ExpandConstant('{param:LANG}') = '');
end;
function IsActiveLang: Boolean;
begin
Result := (LangArray[LangCombo.ItemIndex] = ActiveLanguage);
end;
function ActiveLang: Integer;
var
I: Integer;
begin
for I := 0 to (GetArrayLength(LangArray) - 1) do
begin
if (LangArray[I] = ActiveLanguage) then Result := I;
end;
end;
procedure InitializeWizard;
begin
IsConfirm := True;
LangCombo := TNewComboBox.Create(WizardForm);
LangCombo.Parent := WizardForm.WelcomePage;
LangCombo.Top := WizardForm.Bevel.Top - LangCombo.Height - ScaleY(55);
LangCombo.Left := WizardForm.WelcomeLabel1.Left;
LangCombo.Width := WizardForm.WelcomeLabel1.Width;
LangCombo.Style := csDropDownList;
SelectLangLabel := TNewStaticText.Create(WizardForm);
SelectLangLabel.Parent := WizardForm.WelcomePage;
SelectLangLabel.Top := LangCombo.Top - SelectLangLabel.Height - ScaleY(8);
SelectLangLabel.Left := LangCombo.Left;
SelectLangLabel.Caption := SetupMessage(msgSelectLanguageLabel);
LangCombo.Items.Add('English'); //ItemIndex: 0 - English
LangCombo.Items.Add('Français'); //ItemIndex: 1 - French
LangCombo.Items.Add('Deutsch'); //ItemIndex: 2 - German
LangCombo.Items.Add('Español'); //ItemIndex: 3 - Spanish
//Add languages as you like, but make sure the order matches the order of the languages in the array.
SetArrayLength(LangArray,LangCombo.Items.Count);
LangArray[0] := 'English'; //=ItemIndex: 0
LangArray[1] := 'French'; //=ItemIndex: 1
LangArray[2] := 'German'; //=ItemIndex: 2
LangArray[3] := 'Spanish'; //=ItemIndex: 3
//Add languages as you like, but make sure the order matches the order of the languages in the combobox.
LangCombo.ItemIndex := ActiveLang; //set default language as active language
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
ResultCode: THandle;
begin
Result := True;
if (CurPageID = wpWelcome) and not IsActiveLang then
begin
Result := False;
IsConfirm := False;
ResultCode := ShellExecute(0,'',ExpandConstant('{srcexe}'),'/LANG='+LangArray[LangCombo.ItemIndex],'',SW_SHOW);
if ResultCode <= 32 then MsgBox(Format('Running installer with the selected language failed. Code: %d',[ResultCode]), mbCriticalError, MB_OK);
WizardForm.Close;
end;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := (PageID = wpWelcome) and IsSetLang;
end;
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
Cancel := True;
Confirm := IsConfirm;
end;
This code demonstrates how to create a language combobox on the WelcomePage, but can of course be replaced with any other or custom page.

Try this:
[Setup]
ShowLanguageDialog=yes
ShowUndisplayableLanguages=yes
[Languages]
Name: "cz"; MessagesFile: "compiler:Languages\Czech.isl";
Name: "de"; MessagesFile: "compiler:Languages\German.isl";
Name: "en"; MessagesFile: "compiler:Default.isl";

You cannot change the language on Inno Setup installer while it is running. The installer on the video must be using some custom build of Inno Setup.
But you can re-start the installer with a new language. See these related questions:
Choosing install language programmatically in Inno Setup
Change the setup language while setup is running (Inno Setup)

Related

Inno Setup - Use Input from [Code] to as a parameter after setup of [Files] [duplicate]

This question already has answers here:
How to ask the user to specify a folder name (using Inno Setup)?
(1 answer)
"Identifier Expected" or "Invalid Prototype" when implementing a scripted constant in Inno Setup
(1 answer)
Closed 3 years ago.
I have a piece of the script to get location of Python Home. The [Code] section is as follows -
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define code
#define MyAppName "API DAST"
#define MyAppVersion "0.1"
#define MyAppPublisher "Prateek Inc."
#define MyAppURL "https://prateek.com"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{5547FBEE-AA97-4224-AF61-36C9F720270C}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\API_DAST
DisableDirPage=yes
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputDir=mysetupcompiler
OutputBaseFilename=mysetup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "C:\Users\pnarendr\Desktop\API_DAST\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
; TODO: Change a few config files by running a Python Script. But first, get Python Home from input
Source: "C:\Users\pnarendr\Desktop\output.log"; DestDir: "{code:GetPythonHome}";
[Code]
var
OutputProgressWizardPage: TOutputProgressWizardPage;
OutputProgressWizardPageAfterID: Integer;
procedure InitializeWizard;
var
//InputQueryWizardPage: TInputQueryWizardPage;
//InputOptionWizardPage: TInputOptionWizardPage;
InputDirWizardPage: TInputDirWizardPage;
PrimaryServerPage: TInputQueryWizardPage;
InputFileWizardPage: TInputFileWizardPage;
OutputMsgWizardPage: TOutputMsgWizardPage;
OutputMsgMemoWizardPage: TOutputMsgMemoWizardPage;
AfterID: Integer;
PythonHome: String;
begin
//WizardForm.PasswordEdit.Text := '{#Password}';
AfterID := wpSelectTasks;
//AfterID := CreateCustomPage(AfterID, 'CreateCustomPage', 'ADescription').ID;
//InputQueryWizardPage := CreateInputQueryPage(AfterID, 'CreateInputQueryPage', 'ADescription', 'ASubCaption');
//InputQueryWizardPage.Add('&APrompt:', False);
//AfterID := InputQueryWizardPage.ID;
//InputOptionWizardPage := CreateInputOptionPage(AfterID, 'CreateInputOptionPage', 'ADescription', 'ASubCaption', False, False);
//InputOptionWizardPage.Add('&AOption');
//AfterID := InputOptionWizardPage.ID;
InputDirWizardPage := CreateInputDirPage(AfterID, 'Choose Python Home Folder', '', '', False, '');
InputDirWizardPage.Add('&Location of Python Home:');
InputDirWizardPage.Values[0] := 'C:\Python27'; //Default Value
AfterID := InputDirWizardPage.ID;
InputFileWizardPage := CreateInputFilePage(AfterID, 'CreateInputFilePage', 'ADescription', 'ASubCaption');
InputFileWizardPage.Add('&APrompt:', 'Executable files|*.exe|All files|*.*', '.exe');
//Will this get latest value even if you go back???
PythonHome := InputDirWizardPage.Values[0];
Log('Python Home - '+PythonHome);
AfterID := InputFileWizardPage.ID;
OutputMsgWizardPage := CreateOutputMsgPage(AfterID, 'CreateOutputMsgPage', 'ADescription', 'AMsg');
AfterID := OutputMsgWizardPage.ID;
OutputMsgMemoWizardPage := CreateOutputMsgMemoPage(AfterID, 'CreateOutputMsgMemoPage', 'ADescription', 'ASubCaption', 'AMsg');
AfterID := OutputMsgMemoWizardPage.ID;
OutputProgressWizardPage := CreateOutputProgressPage('CreateOutputProgressPage', 'ADescription');
OutputProgressWizardPageAfterID := AfterID;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
Position, Max: Integer;
begin
if CurPageID = OutputProgressWizardPageAfterID then begin
try
Max := 25;
for Position := 0 to Max do begin
OutputProgressWizardPage.SetProgress(Position, Max);
if Position = 0 then
OutputProgressWizardPage.Show;
Sleep(2000 div Max);
end;
finally
OutputProgressWizardPage.Hide;
end;
end;
Result := True;
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
if SuppressibleMsgBox('Do you want to stop Setup at the Preparing To Install wizard page?', mbConfirmation, MB_YESNO, IDNO) = IDYES then
Result := 'Stopped by user';
end;
function GetPythonHome(Param: String): string;
begin
Result := 'C:\Python27'; //Use default
end;
I don't know how to take InputDirWizardPage.Values[0] as input to run a Python script after setup (to change a config file in the folder copied). How do I do it ?
The Invalid Identifier exception was taken care . Apparently Pascal Script isnt the same as Pascal

Group of Tasks condition inno setup

I´m having difficult to combine conditions in Tasks with GroupDescription. If I don´t to use GroupDescription, it works. I need auto select tasks[0] if tasks[2] is selected. I tried:
[Tasks]
Name: InstallDS; Description: Install DServer?; GroupDescription: InsDS
Name: InstallTG; Description: Install TServer?; GroupDescription: InsDS
Name: InstallOP; Description: Install Optionals?; GroupDescription: InsDS
[Code]
procedure TasksListClickCheck(Sender: TObject);
begin
WizardForm.TasksList.Checked[0] := WizardForm.TasksList.Checked[2];
end;
procedure InitializeWizard;
begin
WizardForm.TasksList.OnClickCheck := #TasksListClickCheck
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpSelectTasks then
begin
TasksListClickCheck(WizardForm.TasksList);
end;
end;
Once you add GroupDescription, the Consecutive Tasks below the group will be arranged as elements 1,2,3. Inno Tasks section description
procedure TasksListClickCheck(Sender: TObject);
begin
if (WizardForm.TasksList.Checked[3] = True) then
begin
WizardForm.TasksList.Checked[1] := True;
end;
end;

Inno Setup - Conditionally hide/show static text based on task selection

[Components]
Name: "Slasher"; Description: "Dagon Slasher"; Types: Slasher Full
Name: "Frankenstein"; Description: "Dagon Frankenstein"; Types: Frankenstein Full
[Types]
Name: "Full"; Description: "Dagon Video Tools"
Name: "Slasher"; Description: "Dagon Slasher"
Name: "Frankenstein"; Description: "Dagon FrankenStein"
[Tasks]
Name: "Debug"; Description: "Nothing"; Components: not Slasher
Name: "Vid"; Description: "Install Extra Codecs for Frankenstein"; Flags: unchecked; Components: not Slasher
[Code]
var
Warning: TNewStaticText;
procedure InitializeWizard;
begin
Warning := TNewStaticText.Create(WizardForm);
Warning.Parent := WizardForm.SelectTasksPage;
Warning.Visible := False;
Warning.AutoSize := False;
Warning.SetBounds(
WizardForm.TasksList.Left,
WizardForm.TasksList.Top + WizardForm.TasksList.Height,
WizardForm.TasksList.Width,
50
);
Warning.Font.Color := clRed;
Warning.Caption := 'Warning: This will result in a non-functional "Join in FrankenStein" button in the Tools Menu.';
end;
I used yet another amazing piece of code by TLama. The problem is I need the note to be visible when the user selects the task, and be hidden otherwise (while on the same page).
You have to handle WizardForm.TasksList.OnClickCheck event and update the Warning label visibility accordingly.
var
Warning: TNewStaticText;
procedure TasksListClickCheck(Sender: TObject);
begin
Warning.Visible :=
{ This (and the task index below) has to be kept in sync with the expression }
{ in "Components" parameter of the respective task. }
{ Though note that in your specific case the test }
{ is redundant as when "Slasher" is selected, you have no tasks, }
{ and the "Tasks" page is completely skipped, so you do not even get here. }
(not IsComponentSelected('Slasher')) and
WizardForm.TasksList.Checked[0]; { You can also use WizardIsTaskSelected }
end;
procedure InitializeWizard;
begin
Warning := TNewStaticText.Create(WizardForm);
...
{ Update Warning label visibility on task selection change }
WizardForm.TasksList.OnClickCheck := #TasksListClickCheck
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpSelectTasks then
begin
{ Update initial visibility }
TasksListClickCheck(WizardForm.TasksList);
end;
end;
Side notes:
Do not hard code the height to fixed 50. Scale it with DPI instead: ScaleY(50).
You should set Warning.WordWrap := True as the caption does not fit page width.
You should shrink TasksList's height as the label does not fit below the list. You are missing the WizardForm.TasksList.Height := WizardForm.TasksList.Height - NoteHeight; from #TLama's code. Again note that he is missing the scaling of the NoteHeight.
const
NoteHeight = 50;
procedure InitializeWizard;
begin
WizardForm.TasksList.Height := WizardForm.TasksList.Height - ScaleY(NoteHeight);
Warning := TNewStaticText.Create(WizardForm);
Warning.Parent := WizardForm.SelectTasksPage;
Warning.AutoSize := False;
Warning.WordWrap := True;
Warning.SetBounds(
WizardForm.TasksList.Left,
WizardForm.TasksList.Top + WizardForm.TasksList.Height,
WizardForm.TasksList.Width,
ScaleY(NoteHeight)
);
Warning.Font.Color := clRed;
{ Update Warning label visibility on task selection change }
WizardForm.TasksList.OnClickCheck := #TasksListClickCheck
Warning.Caption :=
'Warning: This will result in a non-functional "Join in FrankenStein" button ' +
'in the Tools Menu.';
end;

Inno Setup: List all file names in an directory

Am trying to list all files with names in an directory, but unable to do. Is there any way to list all files with names in an directory?
Thanks in advance.
The following script shows how to list all files of a specified directory into a TStrings collection (in this example listed in the list box on a custom page):
[Code]
procedure ListFiles(const Directory: string; Files: TStrings);
var
FindRec: TFindRec;
begin
Files.Clear;
if FindFirst(ExpandConstant(Directory + '*'), FindRec) then
try
repeat
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
Files.Add(FindRec.Name);
until
not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
procedure InitializeWizard;
var
CustomPage: TWizardPage;
FileListBox: TNewListBox;
begin
CustomPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');
FileListBox := TNewListBox.Create(WizardForm);
FileListBox.Parent := CustomPage.Surface;
FileListBox.Align := alClient;
ListFiles('C:\SomeDirectory\', FileListBox.Items);
end;

Passing conditional parameter in Inno Setup

I am new to Inno Setup and I have already read the documentation. Now I know that Inno Setup can accept different/custom parameter and could be processed via Pascal script. But the problem is, I don't know how to write in Pascal.
I am hoping I could get help about the coding.
I'd like to pass /NOSTART parameter to my setup file which while tell the setup to disable(uncheck) the check mark on "Launch " and if /NOSTART is not provided, it it will enable(check) the check mark "Launch "
or if possible, that Launch page is not required and do everything via code.
Since you can't imperatively modify flags for section entries and directly accessing the RunList would be quite a dirty workaround, I'm using for this two postinstall entries, while one has no unchecked flag specified and the second one has. So, the first entry represents the checked launch check box and the second one unchecked launch check box. Which one is used is controlled by the Check parameter function, where is checked if a command line tail contains /NOSTART parameter.
Also, I've used a little more straightforward function for determining if a certain parameter is contained in the command line tail. It uses the CompareText function to compare text in a case insensitive way. You can replace it with CompareStr function, if you want to compare the parameter text in a case sensitive way. Here is the script:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
OutputDir=userdocs:Inno Setup Examples Output
[Run]
Filename: "calc.exe"; Description: "Launch calculator"; \
Flags: postinstall nowait skipifsilent; Check: LaunchChecked
Filename: "calc.exe"; Description: "Launch calculator"; \
Flags: postinstall nowait skipifsilent unchecked; Check: not LaunchChecked
[Code]
function CmdLineParamExists(const Value: string): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to ParamCount do
if CompareText(ParamStr(I), Value) = 0 then
begin
Result := True;
Exit;
end;
end;
function LaunchChecked: Boolean;
begin
Result := not CmdLineParamExists('/NOSTART');
end;
and so a little research read and read .. i got my answer.
here's my code (except the "GetCommandLineParam")
[Code]
{
var
StartNow: Boolean;
}
function GetCommandLineParam(inParam: String): String;
var
LoopVar : Integer;
BreakLoop : Boolean;
begin
{ Init the variable to known values }
LoopVar :=0;
Result := '';
BreakLoop := False;
{ Loop through the passed in arry to find the parameter }
while ( (LoopVar < ParamCount) and
(not BreakLoop) ) do
begin
{ Determine if the looked for parameter is the next value }
if ( (ParamStr(LoopVar) = inParam) and
( (LoopVar+1) <= ParamCount )) then
begin
{ Set the return result equal to the next command line parameter }
Result := ParamStr(LoopVar+1);
{ Break the loop }
BreakLoop := True;
end;
{ Increment the loop variable }
LoopVar := LoopVar + 1;
end;
end;
{
function InitializeSetup(): Boolean;
var
NOSTART_Value : String;
begin
NOSTART_Value := GetCommandLineParam('/NOSTART');
if(NOSTART_Value = 'false') then
begin
StartNow := True
end
else
begin
StartNow := False
end;
Result := True;
end;
}
procedure CurStepChanged(CurStep: TSetupStep);
var
Filename: String;
ResultCode: Integer;
NOSTART_Value : String;
begin
if CurStep = ssDone then
begin
NOSTART_Value := GetCommandLineParam('/NOSTART');
if(NOSTART_Value = 'false') then
begin
Filename := ExpandConstant('{app}\{#MyAppExeName}');
Exec(Filename, '', '', SW_SHOW, ewNoWait, Resultcode);
end
end;
end;
a code update. Thanks to #TLama
function CmdLineParamExists(const Value: string): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to ParamCount do
if CompareText(ParamStr(I), Value) = 0 then
begin
Result := True;
Break;
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
Filename: String;
ResultCode: Integer;
NOSTART_Value : String;
RunApp : Boolean;
begin
if CurStep = ssDone then
begin
RunApp := CmdLineParamExists('/START');
if(RunApp = True) then
begin
Filename := ExpandConstant('{app}\{#MyAppExeName}');
Exec(Filename, '', '', SW_SHOW, ewNoWait, Resultcode);
end
// NOSTART_Value := GetCommandLineParam('/START');
// if(NOSTART_Value = 'true') then
// begin
// Filename := ExpandConstant('{app}\{#MyAppExeName}');
// Exec(Filename, '', '', SW_SHOW, ewNoWait, Resultcode);
//end
end;
end;
How about the following, easy to read
; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Install Specialty Programs"
#define MyAppVersion "1.0"
#define MyAppPublisher ""
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{5}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={pf}\{#MyAppName}
DisableDirPage=yes
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputDir=P:\_Development\INNO Setup Files\Specialty File Install
OutputBaseFilename=Specialty File Install
Compression=lzma
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "P:\_Development\INNO Setup Files\Specialty File Install\Files\0.0 - Steps.docx"; DestDir: "c:\support\Specialty Files"; Tasks: V00Step
[Tasks]
Name: "Office2013"; Description: "Running Office 2013"; Flags: checkablealone unchecked
Name: "Office2016"; Description: "Running Office 2016"; Flags: checkablealone unchecked
Name: "V00Step"; Description: "Steps To Follow (Read Me)"; Flags: exclusive
[Run]
Filename: "C:\Program Files (x86)\Microsoft Office\Office15\WINWORD.EXE"; Parameters: """c:\support\Specialty Files\0.0 - Steps.docx"""; Description: "Run if Office 2013 is installed"; Tasks: V00Step AND Office2013
Filename: "C:\Program Files (x86)\Microsoft Office\Office16\WINWORD.EXE"; Parameters: """c:\support\Specialty Files\0.0 - Steps.docx"""; Description: "Run if Office 2016 is installed"; Tasks: V00Step AND Office2016

Resources