How to modify the Local.config from Innosetup script - inno-setup

I'm having some issues getting this code to function correctly. What I'm trying to accomplish is a user puts in a ConnectionString (during the setup) and its places in a already formatted file. The file is Local.config in the {app}\local directory. I was able to get it to work a few times in the {app} director but now I have nothing.
Source: "Local\Local.config"; DestDir: "{app}\Local"; AfterInstall: ConvertConfig('Local.config'); Flags: ignoreversion
var
UserPage: TInputQueryWizardPage;
xmlFileName: String;
procedure InitializeWizard;
begin
UserPage := CreateInputQueryPage(wpWelcome,
'Pryme Connection String', 'SQL Connecton String', 'Please Enter In SQL Connection String then click Next.');
UserPage.Add('connectionString:', False);
end;
procedure ConvertConfig(xmlFileName: String);
var
xmlFile: String;
xmlInhalt: TArrayOfString;
strName: String;
strTest: String;
tmpConfigFile: String;
k: Integer;
begin
xmlFile := ExpandConstant('{app}') + '\' + 'Local.config';
tmpConfigFile:= ExpandConstant('{app}') + '\config.tmp';
strName := UserPage.Values[0];
if (FileExists(xmlFile)) then begin
//alles in string array speichern
LoadStringsFromFile(xmlFile, xmlInhalt);
//durch Array iterieren
for k:=0 to GetArrayLength(xmlInhalt)-1 do
begin
strTest := xmlInhalt[k];
if (Pos('name="Pryme"', strTest) <> 0 ) then
begin
strTest := ' <add name="Pryme" connectionString="' + strName + '"/> ';
end;
SaveStringToFile(tmpConfigFile, strTest + #13#10, True);
end;
DeleteFile(xmlFile); //delete the old exe.config
RenameFile(tmpConfigFile,xmlFile);
end;
end;

I didn't point to the correct directory.Below is the correct working code.
Source: "Local\Local.config"; DestDir: "{app}\Local"; AfterInstall: ConvertConfig('Local.config'); Flags: ignoreversion
var
UserPage: TInputQueryWizardPage;
xmlFileName: String;
procedure InitializeWizard;
begin
UserPage := CreateInputQueryPage(wpWelcome,
'Pryme Connection String', 'SQL Connecton String', 'Please Enter In SQL Connection String then click Next.');
UserPage.Add('connectionString:', False);
end;
procedure ConvertConfig(xmlFileName: String);
var
xmlFile: String;
xmlInhalt: TArrayOfString;
strName: String;
strTest: String;
tmpConfigFile: String;
k: Integer;
begin
xmlFile := ExpandConstant('{app}\local') + '\' + 'Local.config';
tmpConfigFile:= ExpandConstant('{app}\local') + '\config.tmp';
strName := UserPage.Values[0];
if (FileExists(xmlFile)) then begin
//alles in string array speichern
LoadStringsFromFile(xmlFile, xmlInhalt);
//durch Array iterieren
for k:=0 to GetArrayLength(xmlInhalt)-1 do
begin
strTest := xmlInhalt[k];
if (Pos('name="Pryme"', strTest) <> 0 ) then
begin
strTest := ' <add name="Pryme" connectionString="' + strName + '"/> ';
end;
SaveStringToFile(tmpConfigFile, strTest + #13#10, True);
end;
DeleteFile(xmlFile); //delete the old exe.config
RenameFile(tmpConfigFile,xmlFile);
end;
end;

Related

Inno Setup - Show custom components on Ready to Install page

I would like to add my components and the selected user from the ini file to the Ready to Install page.
Is this even possible?
It should look like this example:
This is my ini file:
[Users]
user1=Program1,Program3
user2=Program1,Program2
user3=Program1,Program3
user4=Program1,Program2
And my script:
[Files]
Source: "TEST \Software\x64\Program_1"; DestDir: "{app}\Program_1"; \
Flags: ignoreversion recursesubdirs; Check: ShouldInstallProgram('Program1')
Source: "TEST \Software\x64\Program_2"; DestDir: "{app}\Program_2"; \
Flags: ignoreversion recursesubdirs; Check: ShouldInstallProgram('Program2')
Source: "TEST \Software\x64\Program_3"; DestDir: "{app}\Program_3"; \
Flags: ignoreversion recursesubdirs; Check: ShouldInstallProgram('Program3')
[Code]
function ShouldInstallProgram(ProgramName: string): Boolean;
var
UserName: string;
ProgramsStr: string;
Programs: TStringList;
begin
UserName := WizardSetupType(False);
ProgramsStr :=
GetIniString('Users', UserName, '', ExpandConstant('{src}\UserPrograms.ini'));
Programs := TStringList.Create;
Programs.CommaText := ProgramsStr;
Result := (Programs.IndexOf(ProgramName) >= 0);
Programs.Free;
end;
Implement UpdateReadyMemo event function. See Add text to 'Ready Page' in Inno Setup
Something like this:
function GetUserName: string;
begin
Result := WizardSetupType(False);
end;
function GetProgramsToInstall: TStrings;
begin
Result := TStringList.Create;
Result.CommaText :=
GetIniString('Users', GetUserName, '', ExpandConstant('{src}\UserPrograms.ini'));
end;
function ShouldInstallProgram(ProgramName: string): Boolean;
var
Programs: TStrings;
begin
Programs := GetProgramsToInstall;
Result := (Programs.IndexOf(ProgramName) >= 0);
Log(Format('Program [%s] - %d', [ProgramName, Result]));
Programs.Free;
end;
procedure AddToReadyMemo(var Memo: string; Info, NewLine: string);
begin
if Info <> '' then Memo := Memo + Info + Newline + NewLine;
end;
function UpdateReadyMemo(
Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo,
MemoGroupInfo, MemoTasksInfo: String): String;
var
Programs: TStrings;
I: Integer;
begin
AddToReadyMemo(Result, MemoUserInfoInfo, NewLine);
AddToReadyMemo(Result, MemoDirInfo, NewLine);
AddToReadyMemo(Result, MemoTypeInfo, NewLine);
AddToReadyMemo(Result, MemoComponentsInfo, NewLine);
AddToReadyMemo(Result, MemoGroupInfo, NewLine);
AddToReadyMemo(Result, MemoTasksInfo, NewLine);
Result :=
Result +
'Selected user:' + NewLine +
Space + GetUserName + NewLine + NewLine;
Programs := GetProgramsToInstall;
if Programs.Count > 0 then
begin
Result := Result + 'Components:' + NewLine;
for I := 0 to Programs.Count - 1 do
Result := Result + Space + Programs[I] + NewLine;
end;
Programs.Free;
end;

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

Passing values into a procedure from NextButtonClicked method Inno Setup

Currently I'm trying to make an installer utility that sets the static IP for the Wi-Fi on Inno Setup. I'm having trouble finding a way to make the correct command insert when the Next button of custom page is pressed. The NextButtonClick method is called correctly however when I actually hit the next button on my page it merely exits without executing the query.
procedure InitializeWizard();
var
Page: TInputQueryWizardPage;
ipAddress, subnetMask, defaultGateway, prefferredDNSServer: String;
ResultCode: Integer;
begin
Page := CreateInputQueryPage(wpWelcome,
'Set Network Config', 'A window for setting the wifi configuration',
'Please indicate the IP address and press next when finished.');
{ Add items (False means it's not a password edit) }
Page.Add('IP Address:', False);
Page.Add('Subnet mask:', False);
Page.Add('Default gateway:', False);
Page.Add('Preferred DNS server:', False);
{ Set initial values (optional) }
Page.Values[0] := ExpandConstant('0.0.0.0');
ipAddress := Page.Values[0]
Page.Values[1] := ExpandConstant('0.0.0.0');
subnetMask := Page.Values[1]
Page.Values[2] := ExpandConstant('0.0.0.0');
defaultGateway := Page.Values[2]
Page.Values[3] := ExpandConstant('0.0.0.0');
prefferredDNSServer := Page.Values[3]
if NextButtonClick(Page.ID) then
begin
Exec('cmd.exe',
'/k ' + 'netsh interface ip set address "Wi-Fi" static ' + ipAddress + ' ' +
subnetMask + ' ' + defaultGateway + ' ' + prefferredDNSServer,
'', SW_SHOW, ewWaitUntilTerminated, ResultCode)
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
ipAddress, subnetMask, defaultGateway, prefferredDNSServer: String;
ResultCode: Integer;
begin
Result := True
Log('NextButtonClick(' + IntToStr(CurPageID) + ') called');
case CurPageID of
100:
{ ipAddress := getParams(ipAddress); }
{ setWifi(ipAddress, subnetMask, defaultGateway, prefferredDNSServer); }
Result:= True;
end;
end;
You do not call the NextButtonClick function yourself. It's an event function, so it's called by Inno Setup.
The code should be like:
var
NetPage: TInputQueryWizardPage;
procedure InitializeWizard();
begin
NetPage :=
CreateInputQueryPage(wpWelcome,
'Set Network Config', 'A window for setting the wifi configuration',
'Please indicate the IP address and press next when finished.');
{ Add items (False means it's not a password edit) }
NetPage.Add('IP Address:', False);
NetPage.Add('Subnet mask:', False);
NetPage.Add('Default gateway:', False);
NetPage.Add('Preferred DNS server:', False);
{ Set initial values (optional) }
NetPage.Values[0] := ExpandConstant('0.0.0.0');
NetPage.Values[1] := ExpandConstant('0.0.0.0');
NetPage.Values[2] := ExpandConstant('0.0.0.0');
NetPage.Values[3] := ExpandConstant('0.0.0.0');
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
ipAddress, subnetMask, defaultGateway, prefferredDNSServer: String;
ResultCode: Integer;
Command: string;
begin
Result := True;
if CurPageID = NetPage.ID then
begin
ipAddress := NetPage.Values[0];
subnetMask := NetPage.Values[1];
defaultGateway := NetPage.Values[2];
prefferredDNSServer := NetPage.Values[3];
Command :=
'netsh interface ip set address "Wi-Fi" static ' +
ipAddress + ' ' + subnetMask + ' ' + defaultGateway + ' ' + prefferredDNSServer;
Exec('cmd.exe', '/C ' + Command, '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
end;
end;
Though, in general, you should do any changes to the target system, until the user confirms the installation by clicking "Install" on the "Ready to Install" page.
While you can use CurPageID = wpReady for that, a more idiomatic approach is using CurStepChanged(ssInstall) (or ssPostInstall):
procedure CurStepChanged(CurStep: TSetupStep);
var
ipAddress, subnetMask, defaultGateway, prefferredDNSServer: String;
ResultCode: Integer;
Command: string;
begin
if CurStep = ssInstall then
begin
ipAddress := NetPage.Values[0];
subnetMask := NetPage.Values[1];
defaultGateway := NetPage.Values[2];
prefferredDNSServer := NetPage.Values[3];
Command :=
'netsh interface ip set address "Wi-Fi" static ' +
ipAddress + ' ' + subnetMask + ' ' + defaultGateway + ' ' + prefferredDNSServer;
Exec('cmd.exe', '/C ' + Command, '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
end;
end;

inno setup : How to get the tcp connections list in windows?

I tried to create an installer to check the current transmission control protocol connections on windows64 machine. Is it possible to create?
am going to use command line using extern. if I give ls -lf it will returns all the files which are currently running on
[code]
const
GetFileExInfoStandard = $0;
type
FILETIME = record
LowDateTime: DWORD;
HighDateTime: DWORD;
end;
WIN32_FILE_ATTRIBUTE_DATA = record
FileAttributes: DWORD;
CreationTime: FILETIME;
LastAccessTime: FILETIME;
LastWriteTime: FILETIME;
FileSizeHigh: DWORD;
FileSizeLow: DWORD;
end;
SYSTEMTIME = record
Year: WORD;
Month: WORD;
DayOfWeek: WORD;
Day: WORD;
Hour: WORD;
Minute: WORD;
Second: WORD;
Milliseconds: WORD;
end;
function GetFileAttributesEx (
FileName: string;
InfoLevelId: DWORD;
var FileInformation: WIN32_FILE_ATTRIBUTE_DATA
): Boolean;
external 'GetFileAttributesExA#kernel32.dll stdcall';
function FileTimeToSystemTime(
FileTime: FILETIME;
var SystemTime: SYSTEMTIME
): Boolean;
external 'FileTimeToSystemTime#kernel32.dll stdcall';
var
TmpfileName: String;
i,j,ResultCode:integer;
ExecStdout,processes:Tarrayofstring;
Page:TInputOptionWizardPage;
procedure initializeWizard;
begin
TmpFileName := ExpandConstant('{tmp}') + '\processes.txt';
Exec('cmd.exe','/C netstat > "' + TmpFileName + '"',
'',SW_HIDE,ewWaitUntilTerminated, ResultCode);
Page := CreateInputOptionPage(wpWelcome,
'Current Running processes on your computer',
'Displays All Running processes on this machine, selecte any process
to terminate','Seleet Any one from the list, Click on next'+#13+
'Note: Do not select System processes this may cause damage to your machine..'
, True, True);
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
if CurPageID = wpwelcome then
begin
if LoadStringsFromFile(TmpFileName, ExecStdout) then
begin
for i:=3 to GetArrayLength(ExecStdout)-1 do
begin
setarraylength(processes,i-2)
processes[i-3]:='';
for j:=1 to length(Execstdout[i]) do
begin
if not ((Execstdout[i][j]=' ') and (Execstdout[i][j+1]=' ')) then
begin
processes[i-3]:=processes[i-3]+execstdout[i][j];
end;
if ((Execstdout[i][j]=' ') and (Execstdout[i][j+1]=' ')) then
j:=length(Execstdout[i]);
end;
page.add(processes[i-3]);
end;
end;
Result:=true;
end;
if CurPageID = page.id then
begin
result:=true;
end;
if CurPageID = wpReady then
Result:=true;
end;
This code is perfectly working but it may take half minute to show the result.
[Code]
function NextButtonClick(CurPage: Integer): Boolean;
var
TmpFileName, ExecStdout: string;
ResultCode: integer;
begin
if CurPage = wpWelcome then begin
TmpFileName := ExpandConstant('{tmp}') + '\ipconfig_results.txt';
Exec('cmd.exe', '/C netstat > "' + TmpFileName + '"', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode);
if LoadStringFromFile(TmpFileName, ExecStdout) then begin
MsgBox(ExecStdout, mbInformation, MB_OK);
// do something with contents of file...
end;
DeleteFile(TmpFileName);
end;
Result := True;
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;

Resources