How to select multiple files in open dialog box in Inno Setup? - inno-setup

These are the two methods in Inno Setup to show file selection dialog,
Wizard Page Method:
[Code]
Var
PageFileDialog: TInputFileWizardPage;
procedure InitializeWizard;
begin
PageFileDialog:= CreateInputFilePage(
wpWelcome,
'Title 1',
'Title 2',
'Title 3');
PageFileDialog:= PageFileDialog.Edits[PageFileDialog.Add('', 'Text file (*.txt)|*.txt', '.txt')];
end;
Direct Open Dialog,
[Code]
procedure InitializeWizard;
var
FileName: string;
begin
FileName := '';
if GetOpenFileName('', FileName, '',
'Text Documents (*.txt)|*.txt|All Files|*.*', 'txt') then
begin
{ Filename contains the selected filename }
end;
end;
But these does no allow to select multiple files in the open dialog, It only selects one file. How to select multiple files?
The method in question Inno Setup with three destination folders does not work here. It should be one textbox and browse button that can select multiple files.

I tested with Inno Setup 6.0.5(u). Other versions may be different.
Take a look at the GetOpenFileNameMulti function:
From the documentation:
Description:
Displays a dialog box that enables the user to select one or more existing file(s). Returns True if the user selected a file, False otherwise. The name of the selected file(s) is returned in the FileNameList list.
Remarks:
An example Filter: 'Text files (.txt)|.txt|All files (.)|.'
Example:
var
FileNameList: TStrings;
begin
{ Create the list }
FileNameList := TStringList.Create;
try
if GetOpenFileNameMulti('', FileNameList, '',
'Text Documents (*.txt)|*.txt|All Files|*.*', 'txt') then
begin
{ Successful; user clicked OK }
{ FileNameList contains the selected filename(s) }
end;
finally
FileNameList.Free;
end;
end;

Related

Custom page with radio buttons for one define

I would like to create a custom Inno Setup page that will be displayed at the very beginning of installation, with 3 radio buttons to select from. That selection should set the value in #define BinVer. Currently I'm forced to make 3 separate installers, but I prefer to have just one with such feature. I'm setting it up like that for each exe:
#define BinVer "111111", in another compilation I change it to #define BinVer "222222", and finaly I have #define BinVer "333333" for the third compilation. I'm using this define in such situations li ke that:
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
case CurUninstallStep of
usPostUninstall:
begin
CreateDir(ExpandConstant('{app}\bin\{#BinVer}\files'));
end;
end;
end;
or
Source: "{#CompPath}\Folder\sed.exe"; DestDir: "{app}\bin\{#BinVer}\files\gui\unbound\"; Flags: deleteafterinstall
So far I have tried something like this, but it's just very beginning, not sure what to do next, I'm not that good with programming it:
[Code]
procedure InitializeWizard();
var
Page: TInputOptionWizardPage;
begin
Page := CreateInputOptionPage(wpWelcome, '', '', '', False, False);
Page.AddEx('Radio button 1', 0, True);
Page.AddEx('Radio button 2', 0, True);
Page.AddEx('Radio button 3', 0, True);
end;
Also tried something like that (but I don't know if this is correct way to achieve this, it's not even compiling without errors):
[Code]
var
BinVer: string;
function InitializeSetup(): Boolean;
var
Page: TInputOptionWizardPage;
begin
Page := CreateInputOptionPage(wpWelcome, 'Select BinVer', 'Select BinVer', '', False, False);
Page.Add('BinVer 1', '111111');
Page.Add('BinVer 2', '222222');
Page.Add('BinVer 3', '333333');
Page.DefaultValueIndex := 0; // initially select the first radio button
Result := True;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
Page: TInputOptionWizardPage;
begin
Result := True;
if CurPageID = wpWelcome then
begin
Page := GetInputOptionPage(wpWelcome);
case Page.SelectedValueIndex of
0: BinVer := '111111';
1: BinVer := '222222';
2: BinVer := '333333';
end;
end;
end;
You cannot change a value of a preprocessor variable (used on compile-time) on runtime.
But you do not have to. You want to use the value on runtime from Pascal Code. And you already have the value stored to runtime Pascal variable (BinVer: string). So use that:
CreateDir(ExpandConstant('{app}\bin\' + BinVer + '\files'));
Though you do not really need to store the value to the global variable either. You can query the "InputOptionPage" when needed.
Example of full code, linking the selection to the [Files] section entry destination:
[Files]
Source: "{#CompPath}\Folder\sed.exe"; \
DestDir: "{app}\bin\{code:GetBinVer}\files\gui\unbound\"; \
Flags: deleteafterinstall
[Code]
var
InputOptionPage: TInputOptionWizardPage;
procedure InitializeWizard();
begin
InputOptionPage := CreateInputOptionPage(wpWelcome, '', '', '', False, False);
InputOptionPage.AddEx('Radio button 1', 0, True);
InputOptionPage.AddEx('Radio button 2', 0, True);
InputOptionPage.AddEx('Radio button 3', 0, True);
// initially select the first radio button
InputOptionPage.SelectedValueIndex := 0;
end;
function GetBinVer(Param: string): string;
begin
case InputOptionPage.SelectedValueIndex of
0: BinVer := '111111';
1: BinVer := '222222';
2: BinVer := '333333';
else RaiseException('Unexpected selection');
end;
end;
(not tested)
Though linking it to a code in CurUninstallStepChanged is more complicated, that happens in another (uninstaller) process. So you will have to store the selection/BinVer somewhere (e.g. Windows Registry), where you will load it from in the uninstaller. You might by able to use SetPreviousData/GetPreviousData.

CreateInputDirPage/TInputDirWizardPage does not create the selected directory

I need to browse or create a new directory at the end of my setup for my database files.
I create an TInputDirWizardPage to choose the directory, and I use a button to launch database installation.
My problem is that the new directory is not created and installation of database fails.
This is my code:
[Code]
var
Page0: TInputQueryWizardPage;
Page1: TInputDirWizardPage;
{ Launch DB CLIP installation }
procedure ButtonOnClick(Sender: TObject);
var
Params: string;
ScriptPath: string;
ResultCode: Integer;
DBPath: string;
Server: String;
Instance: String;
SQL_User: String;
SQL_Password: String;
begin
DBPath := Page1.Values[0];
Server:= Page0.Values[0];
Instance:= Page0.Values[1];
SQL_User:= Page0.Values[2];
SQL_Password:= Page0.Values[3];
ScriptPath := ExpandConstant('"{app}\DB\Create Database 2.12.3.sql"');
Params := '-v CLIPDATA="'+DBPath+'" CLIPINDEX="'+DBPath+'" CLIPLOG="'+DBPath+'" -S '+Server+'\'+Instance+' -U '+SQL_User+' -P '+SQL_Password+' -i '+ScriptPath ;
if MsgBox('' + Params + '', mbInformation, mb_YesNo) = idYes then
Exec ('sqlcmd',Params, '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
Exit;
end;
procedure InitializeWizard();
var
DBButton: TNewButton;
begin
Page0 := CreateInputQueryPage(wpInfoAfter,
'SQL Informations', '',
'Please specify Server and Instance name , then click Next.');
Page0.Add('Server:', False);
Page0.Add('Instance:', False);
Page0.Add('SQL User:', False);
Page0.Add('SQL Password:', True);
Page0.Values[0] := ('localhost');
Page0.Values[1] := ('CLIP');
Page0.Values[2] := ('sa');
Page0.Values[3] := ('clip');
Page1 := CreateInputDirPage(Page0.ID,
'Select CLIP Database files Location', '',
'CLIP DB data files will be stored in the following folder.'#13#10#13#10 +
'To continue, click Next. ' +
'If you would like to select a different folder, click Browse.',
False, 'New Folder');
Page1.Add('Database Folder');
Page1.Values[0] := ExpandConstant('{pf}\CLIP\CLIP_DATA\DB\');
DBButton := TNewButton.Create(Page1);
DBButton.Left := ScaleX(16);
DBButton.Top := ScaleY(205);
DBButton.Width := ScaleX(100);
DBButton.Height := ScaleY(25);
DBButton.Caption := 'Install DB CLIP';
DBButton.OnClick := #ButtonOnClick;
DBButton.Parent := Page1.Surface;
end;
CreateInputDirPage does not create the selected directory on its own.
The Make New Folder button does not create a physical folder. It only creates a virtual node in the tree.
I'm aware that this somewhat contradicts the documentation, which says:
Make New Folder button will be shown that creates a new folder with the specified default name.
If you want to really create a physical folder for the selected path, use CreateDir function in your ButtonOnClick handler.
if not DirExists(DBPath) then
begin
CreateDir(DBPath);
end;

Save entered text to TXT file in Inno Setup

I have to save username and password which typed by user to text file but it create text file and save the texts before user type it. (So empty text file is created).
I think I have to do somethings with procedure but although I search the solution, I couldn't find.
My code:
[Code]
var
Page: TInputQueryWizardPage;
username: String;
password: String;
procedure InitializeWizard;
begin
{ Create the page }
Page := CreateInputQueryPage(wpWelcome,
'Username & Password', 'Username like : e201600',
'Please enter your username and password.');
{ Add items (False means it's not a password edit) }
Page.Add('Username:', False);
Page.Add('Password:', True);
{ Set initial values (optional) }
Page.Values[0] := ExpandConstant('hello5');
Page.Values[1] := ExpandConstant('');
{ Read values into variables }
username := Page.Values[0];
password := Page.Values[1];
SaveStringToFile('c:\filename.txt', username+#13#10+password+#13#10, False);
end;
You are creating the input page when installer starts and immediately saving the fields into text file.
You need to wait while user enters the data and clicks Next button on correct page:
function NextButtonClick(CurPageID: Integer): Boolean;
begin
if(CurPageID = Page.ID) then
begin
{ Process the page }
{ Read values into variables }
username := Page.Values[0];
password := Page.Values[1];
SaveStringToFile('c:\filename.txt', username+#13#10+password+#13#10, False);
end;
Result := True;
end;
And few tips: saving names/passwords is not safe! Also using hardcoded path is reallly unusual...

The Inno Setup action I want after CreateInputQueryPage happens before. Why?

When Running my Inno Setup built installer, the action that I want to have happen as a result of selections in the CreateInputQueryPage happens before the CreateInputQueryPage opens and gets input from the user. What concept am I missing?
Is it that I need to use NextButtonClick?
Here is my Pascal code based on code taken from (http://www.jrsoftware.org/ishelp):
[Code]
procedure UserGroup;
Var Page : TInputQueryWizardPage;
GroupName : String;
Message: String;
ResultCode: Integer;
begin
// Create page
Page := CreateInputQueryPage(wpWelcome,
'Users Group Required',
'Please specify group, then click Next',
'A Windows security group must be created.'
);
// Add items (False means it's not a password edit)
Page.Add('GroupName:', False);
Page.Values[0] := 'SomeGroup';
// Read values into variables
GroupName := Page.Values[0];
if Exec('net.exe', Format( 'localgroup %s /add',[GroupName]), '', SW_SHOW,
ewWaitUntilTerminated, ResultCode) then
begin
// success
Message := Format('The user group %s has been added to the local machine.', [GroupName]);
MsgBox( Message, mbInformation, MB_OK);
end
else begin
// failure i
Message := Format('The installer was not able to set up the %s security group. Please do so manually. (Inno Error Code: %i)', [GroupName, ResultCode]);
MsgBox( Message, mbInformation, MB_OK);
end;
end;
But the MsgBox shows before the CreateInputQueryPage does.

Inno Setup: How to pass variable from [Code] to [Run] (or other section)

How can I pass a variable from [Code] section to parameters in [Run] section in Inno Setup?
Basically, I want to do the following.
Get and save user input to a variable in a procedure InitializeWizard.
Pass the user input to an executable in [Run] section
Here is my code.
[Run]
Filename: "someProgram.exe"; Parameters: ??userInput??
[Code]
procedure InitializeWizard;
var
ConfigPage: TInputQueryWizardPage;
UserInput: String;
begin
{ Create the page }
ConfigPage :=
CreateInputQueryPage(
wpWelcome, 'User input', 'User input',
'Please specify the following information, then click Next.');
{ Add items (False means it's not a password edit) }
ConfigPage.Add('Input here:', False);
{ Set initial values (optional) }
ConfigPage.Values[0] := ExpandConstant('hello');
{ Read values into variables }
UserInput := ConfigPage.Values[0];
end;
Thanks.
You're looking for the scripted constant. See the following example:
[Run]
Filename: "SomeProgram.exe"; Parameters: {code:GetParams}
[Code]
var
ConfigPage: TInputQueryWizardPage;
function GetParams(Value: string): string;
begin
Result := ConfigPage.Values[0];
end;
procedure InitializeWizard;
begin
{ Create the page }
ConfigPage :=
CreateInputQueryPage(
wpWelcome, 'User input', 'User input',
'Please specify the following information, then click Next.');
{ Add items (False means it's not a password edit) }
ConfigPage.Add('Input here:', False);
{ Set initial values (optional) }
ConfigPage.Values[0] := ExpandConstant('hello');
end;

Resources