Allow specific software versions using Inno Setup - inno-setup

Im currently try to understand Inno Setup and Delphi.
The setup should only allow specific patches depending on the already installed software.
My setup has three patches:
Patch1: 1.0 - 2.0
Patch2: 1.0
Patch3: 1.1
For example my installed software has version 1.7.
Then checkbox for Patch1 should be checked.
For version 1.0 only checkboxes for Patch1 and Patch2 should be checked and the other is unchecked.
I programmed it in the function below.
I used the function from How to split a string in Inno Setup.
My question is how to implement it with "check parameter"-function like or how to implement it to with shorter function and more reusability.
Thanks!
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
OutputDir=userdocs:Inno Setup Examples Output
[Types]
Name: Customized; Description: "Select Installations"; Flags: iscustom
[Components]
Name: "Parts"; Description: "Available Patches"; Types: Customized
Name: "Parts\1"; Description: "Version 1.0 - 2.0"; Types: Customized
Name: "Parts\2"; Description: "Version 1.0 "; Types: Customized
Name: "Parts\3"; Description: "Version 1.1)"; Types: Customized
[code]
procedure CurPageChanged(CurPageID: Integer);
var Value1: String;
i, p: Integer;
Dest: TArrayOfString;
Separator: String;
begin
i := 0;
Separator := '.'
// Change Value for testing
Value1 := '1.9'
repeat
SetArrayLength(Dest, i+1);
p := Pos(Separator,Value1);
if p > 0 then begin
Dest[i] := Copy(Value1, 1, p-1);
Value1 := Copy(Value1, p + Length(Separator), Length(Value1));
i := i + 1;
end else begin
Dest[i] := Value1;
Value1 := '';
end;
until Length(Value1)=0;
// 1.0 - 2.0
if (strtoint(Dest[0]) = 1) or (strtoint(Dest[0]) = 2) and (0 <= strtoint(Dest[1])) and (strtoint(Dest[1]) <= 9) then
begin
WizardForm.ComponentsList.Checked[1] := True;
WizardForm.ComponentsList.ItemEnabled[1] := True;
WizardForm.ComponentsList.Checked[2] := False;
WizardForm.ComponentsList.ItemEnabled[2] := False;
WizardForm.ComponentsList.Checked[3] := False;
WizardForm.ComponentsList.ItemEnabled[3] := False;
end;
// 1.0
if (strtoint(Dest[0]) = 1) and (strtoint(Dest[1]) = 0) then
begin
WizardForm.ComponentsList.Checked[1] := True;
WizardForm.ComponentsList.ItemEnabled[1] := True;
WizardForm.ComponentsList.Checked[2] := True;
WizardForm.ComponentsList.ItemEnabled[2] := True;
WizardForm.ComponentsList.Checked[3] := False;
WizardForm.ComponentsList.ItemEnabled[3] := False;
end;
// 1.1
if (strtoint(Dest[0]) = 1) and (1 = strtoint(Dest[1])) then
begin
WizardForm.ComponentsList.Checked[1] := True;
WizardForm.ComponentsList.ItemEnabled[1] := True;
WizardForm.ComponentsList.Checked[2] := False;
WizardForm.ComponentsList.ItemEnabled[2] := False;
WizardForm.ComponentsList.Checked[3] := True;
WizardForm.ComponentsList.ItemEnabled[3] := True;
end;
end;
procedure TypesCombo_OnChange(Sender: TObject);
begin
CurPageChanged(1);
end;
procedure InitializeWizard();
begin
WizardForm.TypesCombo.OnChange := #TypesCombo_OnChange;
end;

If you do not want to allow the user to select what to install, avoid complicating the installer with components. Use Check parameter:
[Files]
Source: "Patch10to20.exe"; DestDir: "{app}"; Check: InstallPatch10to20
Source: "Patch10.exe"; DestDir: "{app}"; Check: InstallPatch10
Source: "Patch11.exe"; DestDir: "{app}"; Check: InstallPatch11
[Code]
var
InstalledVersion: string;
function InstallPatch10to20: Boolean;
begin
Result :=
(CompareVersion('1.0', InstalledVersion) <= 0) and
(CompareVersion(InstalledVersion, '2.0') <= 0);
end;
function InstallPatch10: Boolean;
begin
Result := (CompareVersion('1.0', InstalledVersion) = 0);
end;
function InstallPatch11: Boolean;
begin
Result := (CompareVersion('1.1', InstalledVersion) = 0);
end;
function InitializeSetup: Boolean;
begin
InstalledVersion := '1.9';
Result := True;
end;
The CompareVersion comes from Compare version strings in Inno Setup. Or you can use (new) built-in ComparePackedVersion function.

Related

Installation steps on left side - Inno Setup

Inno Setup - I want to create an installer similar to the screenshot.
The installer should highlight the current step on the left side.
How to achieve the same?
#Bill_Stewart is correct, vanilla Inno Setup does not offer such complex functionality.
However it is possible to do that using Graphical Installer which is a 3rd party extension for Inno Setup (see www.graphical-installer.com for more info).
The implemented functionality (about 150 lines in Pascal):
; This identifier is used for compiling script as Graphical Installer powered installer. Comment it out for regular compiling.
#define GRAPHICAL_INSTALLER_PROJECT
#ifdef GRAPHICAL_INSTALLER_PROJECT
; File with setting for graphical interface
#include "script.graphics.iss"
#else
; Default UI file
#define public GraphicalInstallerUI ""
#endif
[Setup]
AppName=InnoSetupProject
AppVersion=1.5
LicenseFile=readme.txt
DefaultDirName={autoappdata}\InnoSetupProject
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
Compression=lzma2
SolidCompression=yes
OutputDir=Output
OutputBaseFilename=InnoSetupProject
PrivilegesRequired=lowest
; Directive "WizardSmallImageBackColor" was modified for purposes of Graphical Installer.
WizardSmallImageBackColor={#GraphicalInstallerUI}
DisableWelcomePage=no
[Code]
type
TInnoPageStep = record
PageID: Integer;
Caption: String;
Index: Integer;
IsActive: Boolean;
end;
var
AllPagesList: array of TInnoPageStep;
AllPagesCount: Integer;
AllPagesCheckListBox: TNewCheckListBox;
I: Integer;
procedure SetPagesCount(pages: Integer);
begin
AllPagesCount := 0;
SetLength(AllPagesList, pages);
end;
procedure AddPage(pageID: Integer; caption: String);
var
page: TInnoPageStep;
begin
page.Caption := caption;
page.PageID := pageID;
page.Index := AllPagesCount + 1;
AllPagesList[AllPagesCount] := page;
AllPagesCount := AllPagesCount + 1;
end;
procedure CreatePagesListBox();
begin
AllPagesCheckListBox := TNewCheckListBox.Create(WizardForm);
AllPagesCheckListBox.Top := ScaleX(160);
AllPagesCheckListBox.Left := ScaleY(20);
AllPagesCheckListBox.Width := 260;
AllPagesCheckListBox.Height := ScaleY(300);
AllPagesCheckListBox.BorderStyle := bsNone;
AllPagesCheckListBox.ParentColor := True;
AllPagesCheckListBox.MinItemHeight := 30;
AllPagesCheckListBox.ShowLines := False;
AllPagesCheckListBox.WantTabs := True;
AllPagesCheckListBox.Parent := WizardForm;
for I := 0 to AllPagesCount-1 do
begin
AllPagesList[I].Index := AllPagesCheckListBox.AddRadioButton(AllPagesList[I].Caption, '', 0, False, True, nil);
end;
end;
procedure UpdateActivePage(pageID: Integer);
begin
for I := 0 to AllPagesCount-1 do
begin
if (AllPagesList[I].PageID = pageID) then
AllPagesList[I].IsActive := True
else
AllPagesList[I].IsActive := False;
end;
for I := 0 to AllPagesCount-1 do
begin
AllPagesCheckListBox.Checked[AllPagesList[I].Index] := AllPagesList[I].IsActive;
if (AllPagesList[I].IsActive) then
begin
AllPagesCheckListBox.ItemFontStyle[AllPagesList[I].Index] := [fsBold];
AllPagesCheckListBox.ItemFontColor[AllPagesList[I].Index] := clBlack;
end
else
begin
AllPagesCheckListBox.ItemFontStyle[AllPagesList[I].Index] := [];
AllPagesCheckListBox.ItemFontColor[AllPagesList[I].Index] := clWhite;
end;
end;
AllPagesCheckListBox.Invalidate;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
PageChangedGraphicalInstaller(CurPageID);
#endif
UpdateActivePage(CurPageID);
end;
// Next functions are used for proper working of Graphical Installer powered installer
procedure InitializeWizard();
var
pageIDs: array of Integer;
pageCaptions: array of String;
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
InitGraphicalInstaller();
#endif
// This is a list of all standard pages in Inno Setup.
pageIDs := [wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir, wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing, wpInstalling, wpInfoAfter, wpFinished];
pageCaptions := ['wpWelcome', 'wpLicense', 'wpPassword', 'wpInfoBefore', 'wpUserInfo', 'wpSelectDir', 'wpSelectComponents', 'wpSelectProgramGroup', 'wpSelectTasks', 'wpReady', 'wpPreparing', 'wpInstalling', 'wpInfoAfter', 'wpFinished'];
// The setup will have 5 pages
SetPagesCount(5);
// If you are using custom pages you need to add them too
AddPage(pageIDs[0], pageCaptions[0]);
AddPage(pageIDs[1], pageCaptions[1]);
AddPage(pageIDs[5], pageCaptions[5]);
AddPage(pageIDs[11], pageCaptions[11]);
AddPage(pageIDs[13], pageCaptions[13]);
// Init the UI
CreatePagesListBox();
end;
procedure DeInitializeSetup();
begin
#ifdef GRAPHICAL_INSTALLER_PROJECT
DeInitGraphicalInstaller();
#endif
end;
// End of file (EOF)
Please notice: To compile this script you need to install the Graphical Installer. Feel free to ask any other questions (I am developer of GI).

Using combo box to select what paths and registry keys to use

Purpose:
With Inno Setup I want to create an installer with a dropdown list in the install wizard.
The choice made in the wizards defines 2 variables:
One for the folder location and the other for the location in the registry.
Problem:
Variables are defined as global in [Code], but are not used in [Files] and [Registry]
Code:
The two variables are: strData1 & strData2
I was trying to retrieve them with functions: strData1returner & strData2returner
[Setup]
...
[Dirs]
Name: "C:\Program Files\CompanyName\{code:strData1returner}"
[Files]
Source: "C:\SomeDll.dll"; \
DestDir: "C:\Program Files\CompanyName\{code:strData1returner}\"; Flags: ignoreversion;
[Registry]
Root: HKCU; subkey: "{code:strData2returner}"; flags: createvalueifdoesntexist
[Code]
var
Button: TNewButton;
ComboBox: TNewComboBox;
CustomPage: TWizardPage;
strData1: string;
strData2: string;
procedure ComboBoxChange(Sender: TObject);
begin
case ComboBox.ItemIndex of
0:
begin
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
end;
end;
procedure InitializeWizard;
var
DescLabel: TLabel;
begin
CustomPage := CreateCustomPage(wpSelectDir, 'Caption', 'Description');
DescLabel := TLabel.Create(WizardForm);
DescLabel.Parent := CustomPage.Surface;
DescLabel.Left := 0;
DescLabel.Top := 0;
DescLabel.Caption := 'Select an item...';
ComboBox := TNewComboBox.Create(WizardForm);
ComboBox.Parent := CustomPage.Surface;
ComboBox.Left := 0;
ComboBox.Top := DescLabel.Top + DescLabel.Height + 6;
ComboBox.Width := 220;
ComboBox.Style := csDropDownList;
ComboBox.Items.Add('Choice1');
ComboBox.ItemIndex := 0;
ComboBox.OnChange := #ComboBoxChange;
end;
function strData1returner(Param: String): String;
begin
Result := strData1;
end;
function strData2returner(Param: String): String;
begin
Result := strData2;
end;
There was only a single option: "Choice1" - So I added a second (Choice2), and alternative values for that second option, under index 1.
You should also initialize the two variables in InitializeWizard, in case the user doesn't change the combobox value. The ComboBoxChange procedure is only executed when the value actually changes, not when the default is accepted via no action.
Also, in trying to reproduce your problem I noticed a syntax problem causing compilation errors with createvalueifdoesntexistcreatevalueifdoesntexist - naturally, you just need one of those.
[Dirs]
Name: "C:\Program Files\CompanyName\{code:strData1returner}"
[Files]
Source: "C:\SomeDll.dll"; DestDir: "C:\Program Files\CompanyName\{code:strData1returner}\"; Flags: ignoreversion;
[Registry]
Root: HKCU; subkey:"{code:strData2returner}"; flags: createvalueifdoesntexist
[Code]
var
Button: TNewButton;
ComboBox: TNewComboBox;
CustomPage: TWizardPage;
strData1: string;
strData2: string;
procedure ComboBoxChange(Sender: TObject);
begin
case ComboBox.ItemIndex of
0:
begin
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
1:
begin
strData1 := 'Subfolder2';
strData2 := 'SOFTWARE\CompanyName2';
end;
end;
end;
procedure InitializeWizard;
var
DescLabel: TLabel;
begin
CustomPage := CreateCustomPage(wpSelectDir, 'Caption', 'Description');
DescLabel := TLabel.Create(WizardForm);
DescLabel.Parent := CustomPage.Surface;
DescLabel.Left := 0;
DescLabel.Top := 0;
DescLabel.Caption := 'Select an item...';
ComboBox := TNewComboBox.Create(WizardForm);
ComboBox.Parent := CustomPage.Surface;
ComboBox.Left := 0;
ComboBox.Top := DescLabel.Top + DescLabel.Height + 6;
ComboBox.Width := 220;
ComboBox.Style := csDropDownList;
ComboBox.Items.Add('Choice1');
ComboBox.Items.Add('Choice2');
ComboBox.ItemIndex := 0;
ComboBox.OnChange := #ComboBoxChange;
strData1 := 'Subfolder';
strData2 := 'SOFTWARE\CompanyName';
end;
function strData1returner(Param: String): String;
begin
Result := strData1;
end;
function strData2returner(Param: String): String;
begin
Result := strData2;
end;
The code above is working as I think you expect it to here.
Actually your attempt to use global variables just complicates the code.
Access the ComboBox.ItemIndex directly from scripted constant implementations like:
[Dirs]
Name: "{app}\{code:GetSelectedSubfolder}"
[Files]
Source: "C:\SomeDll.dll"; DestDir: "{app}\{code:GetSelectedSubfolder}"
[Registry]
Root: HKCU; Subkey: "{code:GetSelectedSubkey}"
[Code]
var
ComboBox: TNewComboBox;
procedure InitializeWizard;
{ ... }
begin
{ ... }
ComboBox := TNewComboBox.Create(WizardForm);
{ ... }
ComboBox.Items.Add('Choice1');
ComboBox.Items.Add('Choice2');
ComboBox.ItemIndex := 0;
end;
function GetSelectedSubfolder(Param: String): String;
begin
case ComboBox.ItemIndex of
0: Result := 'Subfolder1';
1: Result := 'Subfolder2';
end;
end;
function GetSelectedSubkey(Param: String): String;
begin
case ComboBox.ItemIndex of
0: Result := 'SOFTWARE\CompanyName1';
1: Result := 'SOFTWARE\CompanyName2';
end;
end;
You can create global variables like this:
#define CustomVarName "Value"
More specific information about here: #define

Add image into the components list - component description

I would like to display a little image, when user hovers mouse cursor over a component on the "Select Components" page.
For example, I would like to do something like this:
I found a half solution here: Long descriptions on Inno Setup components.
But I'm missing the image part.
Building upon my answer to Long descriptions on Inno Setup components. You will need to copy HoverTimerProc and its supporting functions and global variables.
This answer modifies the HoverComponentChanged and InitializeWizard procedures to support the images in addition to description labels.
[Files]
...
Source: Main.bmp; Flags: dontcopy
Source: Additional.bmp; Flags: dontcopy
Source: Help.bmp; Flags: dontcopy
[Code]
var
CompLabel: TLabel;
CompImage: TBitmapImage;
LoadingImage: Boolean;
procedure HoverComponentChanged(Index: Integer);
var
Description: string;
Image: string;
ImagePath: string;
begin
case Index of
0: begin Description := 'This is the description of Main Files'; Image := 'main.bmp'; end;
1: begin Description := 'This is the description of Additional Files'; Image := 'additional.bmp'; end;
2: begin Description := 'This is the description of Help Files'; Image := 'help.bmp'; end;
else
Description := 'Move your mouse over a component to see its description.';
end;
CompLabel.Caption := Description;
if Image <> '' then
begin
{ The ExtractTemporaryFile pumps the message queue, prevent recursion }
if not LoadingImage then
begin
LoadingImage := True;
try
ImagePath := ExpandConstant('{tmp}\' + Image);
if not FileExists(ImagePath) then
begin
ExtractTemporaryFile(Image);
end;
CompImage.Bitmap.LoadFromFile(ImagePath);
finally
LoadingImage := False;
end;
end;
CompImage.Visible := True;
end
else
begin
CompImage.Visible := False;
end;
end;
procedure InitializeWizard();
var
HoverTimerCallback: LongWord;
begin
{ For HoverTimerProc and its supporting functions, }
{ see https://stackoverflow.com/q/10867087/850848#37796528 }
HoverTimerCallback := WrapTimerProc(#HoverTimerProc, 4);
SetTimer(0, 0, 50, HoverTimerCallback);
CompLabel := TLabel.Create(WizardForm);
CompLabel.Parent := WizardForm.SelectComponentsPage;
CompLabel.Left := WizardForm.ComponentsList.Left;
CompLabel.Width := (WizardForm.ComponentsList.Width - ScaleX(16)) div 2;
CompLabel.Height := ScaleY(64);
CompLabel.Top := WizardForm.ComponentsList.Top + WizardForm.ComponentsList.Height - CompLabel.Height;
CompLabel.AutoSize := False;
CompLabel.WordWrap := True;
CompImage := TBitmapImage.Create(WizardForm);
CompImage.Parent := WizardForm.SelectComponentsPage;
CompImage.Top := CompLabel.Top;
CompImage.Width := CompImage.Width;
CompImage.Height := CompLabel.Height;
CompImage.Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width - CompLabel.Width;
WizardForm.ComponentsList.Height := WizardForm.ComponentsList.Height - CompLabel.Height - ScaleY(8);
end;

how to pass a variable value to an xml file?

this is my code to enter a port number from user.upon installing i want to get the port number changed in apache tomcat server.xml file.
Iam passing apache tomcat zip file also using files section and unzip it in run section
var
javaVersion: String;
javaPath: String;
//port number code
function SetFocus(hWnd: HWND): HWND;
external 'SetFocus#user32.dll stdcall';
var
SerialPage: TWizardPage;
SerialEdits: array of TEdit;
const
CF_TEXT = 1;
VK_BACK = 8;
SC_EDITCOUNT = 1;
SC_CHARCOUNT = 4;
procedure OnSerialEditChange(Sender: TObject);
var
I: Integer;
CanContinue: Boolean;
begin
CanContinue := True;
for I := 0 to GetArrayLength(SerialEdits) - 1 do
if Length(SerialEdits[I].Text) < SC_CHARCOUNT then
begin
CanContinue := False;
Break;
end;
WizardForm.NextButton.Enabled := CanContinue;
end;
function GetSerialNumber(Param: String): string;
var
I: Integer;
begin
Result := '';
for I := 0 to GetArrayLength(SerialEdits) - 1 do
Result := Result + SerialEdits[I].Text ;
end;
procedure OnSerialEditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Edit: TEdit;
EditIndex: Integer;
begin
Edit := TEdit(Sender);
EditIndex := Edit.TabOrder - SerialEdits[0].TabOrder;
if (EditIndex = 0) and (Key = Ord('V')) and (Shift = [ssCtrl]) then
begin
if TryPasteSerialNumber then
Key := 0;
end
else
if (Key >= 32) and (Key <= 255) then
begin
if Length(Edit.Text) = SC_CHARCOUNT - 1 then
begin
if EditIndex < GetArrayLength(SerialEdits) - 1 then
SetFocus(SerialEdits[EditIndex + 1].Handle)
else
SetFocus(WizardForm.NextButton.Handle);
end;
end
else
if Key = VK_BACK then
if (EditIndex > 0) and (Edit.Text = '') and (Edit.SelStart = 0) then
SetFocus(SerialEdits[EditIndex - 1].Handle);
end;
procedure CreateSerialNumberPage;
var
I: Integer;
Edit: TEdit;
DescLabel: TLabel;
EditWidth: Integer;
begin
SerialPage := CreateCustomPage(wpWelcome, 'Serial number validation',
'Enter the valid serial number');
DescLabel := TLabel.Create(SerialPage);
DescLabel.Top := 16;
DescLabel.Left := 0;
DescLabel.Parent := SerialPage.Surface;
DescLabel.Caption := 'Enter the valid serial number and continue with the installation...';
DescLabel.Font.Style := [fsBold];
SetArrayLength(SerialEdits, SC_EDITCOUNT);
EditWidth := (SerialPage.SurfaceWidth - ((SC_EDITCOUNT - 1) * 8)) div SC_EDITCOUNT;
for I := 0 to SC_EDITCOUNT - 1 do
begin
Edit := TEdit.Create(SerialPage);
Edit.Top := 40;
Edit.Left := I * (EditWidth + 8);
Edit.Width := EditWidth;
Edit.CharCase := ecUpperCase;
Edit.MaxLength := SC_CHARCOUNT;
Edit.Parent := SerialPage.Surface;
Edit.OnChange := #OnSerialEditChange;
Edit.OnKeyDown := #OnSerialEditKeyDown;
SerialEdits[I] := Edit;
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = SerialPage.ID then
WizardForm.NextButton.Enabled := False;
end;
procedure InitializeWizard;
begin
CreateSerialNumberPage;
end ;
i want to replace the port number which was entered by user in tomcats server.xml using tokens
<Connector port="##portnumber##" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
Here's a script I've made for you. I've changed the way of entering port number and shown how to modify attribute values in XML files. Also notice the usage of the AfterInstall function:
#define TomcatDest "{app}\tomcat"
#define TomcatFullPath TomcatDest + "\apache-tomcat-7.0.42"
#define TomcatSrvConfigFile TomcatFullPath + "\conf\server.xml"
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Files]
Source: "unzip.exe"; DestDir: "{tmp}\installertemps"
Source: "apache-tomcat-7.0.42.zip"; DestDir: "{tmp}\installertemps"
[Run]
Filename: "{tmp}\installertemps\unzip.exe"; Parameters: " ""{tmp}\installertemps\apache-tomcat-7.0.42.zip"" -d ""{#TomcatDest}"" "; AfterInstall: UpdateConfigFile(ExpandConstant('{#TomcatSrvConfigFile}'))
[Code]
const
DefaultPort = 8080;
var
ConfigPage: TInputQueryWizardPage;
procedure SaveAttrValueToXML(const FileName, NodePath, Attribute,
Value: string);
var
XMLNode: Variant;
XMLDocument: Variant;
begin
XMLDocument := CreateOleObject('Msxml2.DOMDocument');
try
XMLDocument.async := False;
XMLDocument.load(FileName);
if (XMLDocument.parseError.errorCode <> 0) then
MsgBox('The XML file could not be parsed. ' +
XMLDocument.parseError.reason, mbError, MB_OK)
else
begin
XMLDocument.setProperty('SelectionLanguage', 'XPath');
XMLNode := XMLDocument.selectSingleNode(NodePath);
XMLNode.setAttribute(Attribute, Value);
XMLDocument.save(FileName);
end;
except
MsgBox('An error occured!' + #13#10 + GetExceptionMessage,
mbError, MB_OK);
end;
end;
procedure InitializeWizard;
begin
ConfigPage := CreateInputQueryPage(wpSelectDir, 'Tomcat configuration',
'Description', 'SubCaption');
ConfigPage.Add('Port:', False);
ConfigPage.Values[0] := IntToStr(DefaultPort);
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
PortNumber: Integer;
begin
Result := True;
if CurPageID = ConfigPage.ID then
begin
PortNumber := StrToIntDef(ConfigPage.Values[0], -1);
// modify the statement to allow users enter only valid port numbers;
// currently the value of -1 means that there is not even a number entered
// in the edit box
if (PortNumber = -1) then
begin
Result := False;
MsgBox('You''ve entered invalid port number. The setup cannot continue...', mbError, MB_OK);
end;
end;
end;
procedure UpdateConfigFile(const FileName: string);
begin
SaveAttrValueToXML(FileName, '//Server/Service/Connector', 'port',
ConfigPage.Values[0]);
end;

TasksList - how to move TasksList to other WizardForm Page and keep it's content?

When I'm trying to change TasksList's Parent, I get an empty list as the result.
WizardForm.TasksList.Parent := WizardForm.DirEdit.Parent;
WizardForm.TasksList.Top := WizardForm.DirEdit.Top + WizardForm.DirEdit.Height + ScaleY(8);
WizardForm.TasksList.Left := WizardForm.DirEdit.Left;
WizardForm.TasksList.Height := ScaleY(100);
Alternate solution is to create own checkboxes for tasks:
[Icons]
Name: "{group}\{#MyAppName1}"; Filename: "{app}\{#MyAppName1}\{#MyAppExeName}"; WorkingDir: "{app}\{#MyAppName1}"; Check: menuicons; Components: G3EE;
Name: "{group}\{#MyAppName2}"; Filename: "{app}\{#MyAppName2}\{#MyAppExeName2}"; WorkingDir: "{app}\{#MyAppName2}"; Check: menuicons; Components: G3ZBEE;
Name: "{commondesktop}\{#MyAppName2}"; Filename: "{app}\{#MyAppName2}\{#MyAppExeName2}"; WorkingDir: "{app}\{#MyAppName2}"; Check: desktopicon; Components: G3ZBEE;
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName2}"; Filename: "{app}\{#MyAppName2}\{#MyAppExeName2}"; WorkingDir: "{app}\{#MyAppName2}"; Check: quicklaunchicon; Components: G3ZBEE;
[Code]
Var
DesktopIconCheckBox: TCheckBox;
StartMenuCheckBox: TCheckBox;
QuickStartCheckBox: TCheckBox;
function desktopicon(): Boolean;
begin
Result := DesktopIconCheckBox.Checked;
end;
function menuicons(): Boolean;
begin
Result := StartMenuCheckBox.Checked;
end;
function quicklaunchicon(): Boolean;
begin
if GetWindowsVersion < $06000000 then begin
Result := QuickStartCheckBox.Checked;
end;
end;
procedure InitializeWizard();
var
ItemsGap: Integer;
begin
ItemsGap := WizardForm.DirBrowseButton.Left - (WizardForm.DirEdit.Left + WizardForm.DirEdit.Width);
DesktopIconCheckBox := TCheckBox.Create(WizardForm.DirEdit.Owner);
DesktopIconCheckBox.Visible := true;
DesktopIconCheckBox.Checked := true;
StartMenuCheckBox := TCheckBox.Create(WizardForm.DirEdit.Owner);
StartMenuCheckBox.Visible := true;
StartMenuCheckBox.Checked := true;
if GetWindowsVersion < $06000000 then begin
QuickStartCheckBox := TCheckBox.Create(WizardForm.DirEdit.Owner);
QuickStartCheckBox.Visible := true;
QuickStartCheckBox.Checked := false;
end;
if true then
begin
DesktopIconCheckBox.Top := WizardForm.DirEdit.Top + WizardForm.DirEdit.Height + ItemsGap / 2;
DesktopIconCheckBox.Width := WizardForm.DirEdit.Width;
DesktopIconCheckBox.Caption := ExpandConstant('{cm:CreateDesktopIcon}');
DesktopIconCheckBox.Parent := WizardForm.DirEdit.Parent;
StartMenuCheckBox.Top := DesktopIconCheckBox.Top + DesktopIconCheckBox.Height + ItemsGap / 2;
StartMenuCheckBox.Width := WizardForm.DirEdit.Width;
StartMenuCheckBox.Caption := ExpandConstant('{cm:MenuStartIcons}');
StartMenuCheckBox.Parent := WizardForm.DirEdit.Parent;
if GetWindowsVersion < $06000000 then begin
QuickStartCheckBox.Top := StartMenuCheckBox.Top + StartMenuCheckBox.Height + ItemsGap / 2;
QuickStartCheckBox.Width := WizardForm.DirEdit.Width;
QuickStartCheckBox.Caption := ExpandConstant('{cm:CreateQuickLaunchIcon}');//SetupMessage(msgNoProgramGroupCheck2);
QuickStartCheckBox.Parent := WizardForm.DirEdit.Parent;
end;
end;
end;

Resources