I am creating a set up which involves in conditionally skipping pages based on a value I get in the 3rd page. I create all the possible pages in the InitializeWizard() and while debugging I can see all the pages created. When I try to skip pages in the ShouldSkipPage, I am unable to skip as I expected.
At which scenario a page becomes invalid or is there any way to check through log or something about the status of the page.
P.S - The page is very much valid and available and I am only not able to skip it.
The code snippet is given below...
[Code]
var
PageSQL2008SetupFile2: Integer;
PageSQL2008R2SetupFile2: Integer;
PageSQL2012SetupFile2: Integer;
PageSQL2014SetupFile2: Integer;
procedure InitializeWizard();
begin
MyModeTypical := false;
PageProductName := CreateInputQueryPage(wpSelectComponents,
'Settings',
'Product Name',
'Please specify the product name, then click Next.');
PageProductName.Add('Product Name:', False);
PageProductName.Values[0] := ProductName;
//SQL Server selection page
PageSQLServerSelection := CreateInputOptionPage(PageProductName.ID,
'SQL Server Selection', 'Please select the version of SQL Server you want to install.',
'',
True, False);
PageSQLServerSelection.Add('SQL 2008');
PageSQLServerSelection.Add('SQL 2008R2');
PageSQLServerSelection.Add('SQL 2012');
PageSQLServerSelection.Add('SQL 2014');
PageSQLServerSelection.Values[0] := False;
PageSQLServerSelection.Values[1] := False;
PageSQLServerSelection.Values[2] := False;
PageSQLServerSelection.Values[3] := False;
// Creating Setup pages for the 4 servers
PageSQL2008SetupFile2 := MSSQL2008SETUPDIR_CreatePage(PageSQLServerSelection.ID);
PageSQL2008R2SetupFile2 := MSSQL2008R2SETUPDIR_CreatePage(PageSQL2008SetupFile2);
PageSQL2012SetupFile2 := MSSQL2012SETUPDIR_CreatePage(PageSQL2008R2SetupFile2);
PageSQL2014SetupFile2 := MSSQL2014SETUPDIR_CreatePage(PageSQL2012SetupFile2);
// some more logic...
end;
// Function for creating the Setup pages for 4 SQL Servers (Same logic for all 4 servers)
function MSSQL2008SETUPDIR_CreatePage(PreviousPageId: Integer): Integer;
var
Page: TWizardPage;
BMPFile: String;
begin
SelectedSQLServerVersion := GetSQLServerVersion('');
Page := CreateCustomPage(
PreviousPageId,
ExpandConstant('Database Settings'),
ExpandConstant('Special note for the Microsoft SQL Server 2008 Setup')
);
BMPFile:= ExpandConstant('{tmp}\caution.bmp');
if not FileExists(BMPFile) then ExtractTemporaryFile(ExtractFileName(BMPFile));
{ BitmapImage1 }
BitmapImage1 := TBitmapImage.Create(Page);
with BitmapImage1 do
begin
Bitmap.LoadFromFile(BMPFile);
Parent := Page.Surface;
Left := ScaleX(8);
Top := ScaleY(8);
Width := ScaleX(97);
Height := ScaleY(209);
end;
{ NewStaticText1 }
NewStaticText1 := TNewStaticText.Create(Page);
with NewStaticText1 do
begin
Parent := Page.Surface;
Caption := 'To install Microsoft SQL Server 2008 you have to insert the Microsoft SQL Server 2008 Setup CD, when XXX setup requests it. The installation path of your Microsoft SQL Server 2008 setup and the additional Service Packs can be defined on the next pages.';
Left := ScaleX(112);
Top := ScaleY(8);
Width := ScaleX(292);
Height := ScaleY(77);
AutoSize := False;
TabOrder := 0;
WordWrap := True;
end;
{ NewStaticText2 }
NewStaticText2 := TNewStaticText.Create(Page);
with NewStaticText2 do
begin
Parent := Page.Surface;
Caption :=
'CAUTION: When autorun is activated, dont click in the autorun menu of Microsoft SQL Server 2008.' + #13 +
'Otherwise you must reboot your machine and restart the setup !';
Left := ScaleX(112);
Top := ScaleY(88);
Width := ScaleX(293);
Height := ScaleY(62);
AutoSize := False;
Font.Color := -16777208;
Font.Height := ScaleY(-11);
Font.Name := 'Tahoma';
Font.Style := [fsBold];
ParentFont := False;
TabOrder := 1;
WordWrap := True;
end;
with Page do
begin
//OnActivate := #MSSQLSETUPDIR_Activate;
//OnShouldSkipPage := #MSSQLSETUPDIR_ShouldSkipPage;
//OnBackButtonClick := #MSSQLSETUPDIR_BackButtonClick;
//OnNextButtonClick := #MSSQLSETUPDIR_NextButtonClick;
//OnCancelButtonClick := #MSSQLSETUPDIR_CancelButtonClick;
end;
Result := Page.ID;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
var
begin
if PageID = wpSelectComponents then begin
Result := MyModeTypical;
end else if PageID = PageProductName.ID then begin
Result := MyModeTypical;
end;
Log('Server is...' + SelectedSQLServerVersion);
if SelectedSQLServerVersion <> '' then begin
// Database Settings Warning
if (SQLServer2008Flag = True) and (IsComponentSelected('DBS\SERVER')) then begin
if PageID = PageSQL2008SetupFile2 then begin
Result := false;
end else if PageID = PageSQL2008R2SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2012SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2014SetupFile2 then begin
Result := true;
end;
end else if (SQLServer2008R2Flag = True) and (IsComponentSelected('DBS\SERVER')) then begin
if PageID = PageSQL2008R2SetupFile2 then begin
Result := false;
end else if PageID = PageSQL2012SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2014SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2008SetupFile2 then begin
Result := true;
end;
end else if (SQLServer2012Flag = True) and (IsComponentSelected('DBS\SERVER')) then begin
if PageID = PageSQL2012SetupFile2 then begin
Result := false;
// This PageSQL2014SetupFile2 is not skipped.....
end else if PageID = PageSQL2014SetupFile2 then begin
Result := true;
// This PageSQL2008SetupFile2 and PageSQL2008R2SetupFile2 are skipped properly.....
end else if PageID = PageSQL2008SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2008R2SetupFile2 then begin
Result := true;
end;
end else if (SQLServer2014Flag = True) and (IsComponentSelected('DBS\SERVER')) then begin
if PageID = PageSQL2014SetupFile2 then begin
Result := false;
end else if PageID = PageSQL2008SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2008R2SetupFile2 then begin
Result := true;
end else if PageID = PageSQL2012SetupFile2 then begin
Result := true;
end;
end;
// some more logic
end;
DeeJay
Related
I'm trying to create something like this:
I want the check box to be hidden behind the lock image, and clicking on it will open a form requesting code entry, and if the code is correct the image will be removed and the check box will be available.
Here's what I tried:
[files]
Source: "Lock.bmp"; Flags: dontcopy
{...}
[code]
var
CustomFuncPage: TWizardPage;
CBAdvFunctions: TNewCheckBox;
Locked: TBitmapImage;
procedure OnClickLock(Sender: TObject);
var
PassForm: TSetupForm;
Edit: TNewEdit;
OKButton, CancelButton: TNewButton;
begin
PassForm := CreateCustomForm();
PassForm.ClientWidth := ScaleX(256);
PassForm.ClientHeight := ScaleY(128);
PassForm.Caption := 'Password required';
Edit := TNewEdit.Create(PassForm);
Edit.Top := ScaleY(10);
Edit.Left := ScaleX(10);
Edit.Width := PassForm.ClientWidth - ScaleX(20);
Edit.Height := ScaleY(23);
Edit.Anchors := [akLeft, akTop, akRight];
Edit.Parent := PassForm;
OKButton := TNewButton.Create(PassForm);
OKButton.Parent := PassForm;
OKButton.Caption := 'OK';
OKButton.Left := PassForm.ClientWidth - ScaleX(166);
OKButton.Top := PassForm.ClientHeight - ScaleY(33);
OKButton.Height := ScaleY(23);
OKButton.Anchors := [akRight, akBottom]
OKButton.ModalResult := mrOk;
OKButton.Default := True;
CancelButton := TNewButton.Create(PassForm);
CancelButton.Parent := PassForm;
CancelButton.Caption := 'Cancel';
CancelButton.Left := PassForm.ClientWidth - ScaleX(85);
CancelButton.Top := PassForm.ClientHeight - ScaleY(33);
CancelButton.Height := ScaleY(23);
CancelButton.Anchors := [akRight, akBottom]
CancelButton.ModalResult := mrCancel;
CancelButton.Cancel := True;
PassForm.ActiveControl := Edit;
if PassForm.ShowModal() = mrOk then
begin
if Edit.Text = '1234' then
begin
Locked.Free;
PassForm.Free;
end else
begin
MsgBox('Password incorrect', mbError, MB_OK);
PassForm.Free;
end;
end else
begin
PassForm.Free;
end;
end;
Procedure InitializeWizard;
begin
CustomFuncPage := CreateCustomPage(wpSelectProgramGroup, {...}, {...});
CBAdvFunctions := TNewCheckBox.Create(CustomFuncPage);
CBAdvFunctions.Parent := CustomFuncPage.Surface;
CBAdvFunctions.Top := 0;
CBAdvFunctions.Left := 0;
CBAdvFunctions.Caption := 'Advanced Functions'
CBAdvFunctions.Width := ScaleX(130);
CBAdvFunctions.Cursor := 1;
CBAdvFunctions.SendToBack;
ExtractTemporaryFile('Lock.bmp');
Locked := TBitmapImage.Create(CustomFuncPage);
Locked.Parent := CustomFuncPage.Surface;
Locked.Bitmap.LoadFromFile(ExpandConstant('{tmp}\Lock.bmp'));
Locked.Bitmap.AlphaFormat := afPremultiplied;
Locked.SetBounds(0, 0, CBAdvFunctions.Width, CBAdvFunctions.Height);
Locked.Stretch := True;
Locked.BringToFront;
Locked.OnClick := #OnClickLock;
{...}
And this is the result:
This is the image I used:
I tried a few ways, but was unable to get the image to cover the checkbox.
Maybe someone has an idea?
By the way, maybe someone has an explanation for why the background of the image is not transparent?
Does anyone know of a sample or can provide a sample of how to use the Restart Manager built-in to Windows to close explorer.exe at the beginning of the uninstall process of Inno Setup then restarting it just after files removed ? I have some shell items that even after unregistered is still allocated and can't be removed until explorer.exe is closed.
TIA!!
Here's an example of how to do it:
{ Example how to use RestartManager and Offer Option to Delete App Data during Uninstall of Inno Setup }
{ Combined multiple open source ISS code found with some custom changes }
{ This could probably be cleaned up a bit, my goal was to get something to work. }
{ I also stripped it down a bit as I had multiple applications and data so hope }
{ everything removed without an issue, but I'm sure you can figure it out if so }
{-------------------------------------------------------------------------}
{ Copies a NULL-terminated array of characters to a string. }
function ArrayToString(Chars:array of Char):String;
var
Len,i:Longint;
begin
Len:=GetArrayLength(Chars);
SetLength(Result,Len);
i:=0;
while (i<Len) and (Chars[i]<>#0) do begin
Result[i+1]:=Chars[i];
i:=i+1;
end;
SetLength(Result,i);
end;
{-------------------------------------------------------------------------}
type
LONG = Longint;
ULONG = Cardinal;
IdList=array of DWORD;
ProcessEntry=record
ID:DWORD;
Name:String;
Restartable,ToTerminate:Boolean;
end;
ProcessList=array of ProcessEntry;
{
Code for Windows Vista and above
}
const
{ Return codes. }
ERROR_SUCCESS = 0;
ERROR_MORE_DATA = 234;
INVALID_HANDLE_VALUE = -1;
CCH_RM_SESSION_KEY = 32;
CCH_RM_MAX_APP_NAME = 255;
CCH_RM_MAX_SVC_NAME = 63;
RmUnknownApp = 0; { The application cannot be classified as any other type. An application of this type can only be shut down by a forced shutdown. }
RmMainWindow = 1; { A Windows application run as a stand-alone process that displays a top-level window. }
RmOtherWindow = 2; { A Windows application that does not run as a stand-alone process and does not display a top-level window. }
RmService = 3; { The application is a Windows service. }
RmExplorer = 4; { The application is Windows Explorer. }
RmConsole = 5; { The application is a stand-alone console application. }
RmCritical = 1000; { A system restart is required to complete the installation because a process cannot be shut down. }
RmStatusUnknown = $0000;
RmStatusRunning = $0001;
RmStatusStopped = $0002;
RmStatusStoppedOther = $0004;
RmStatusRestarted = $0008;
RmStatusErrorOnStop = $0010;
RmStatusErrorOnRestart = $0020;
RmStatusShutdownMasked = $0040;
RmStatusRestartMasked = $0080;
RmForceShutdown = $0001;
RmShutdownOnlyRegistered = $0010;
type
SessionKey=array[1..CCH_RM_SESSION_KEY+1] of Char;
FILETIME=record
dwLowDateTime,dwHighDateTime:DWORD;
end;
RM_UNIQUE_PROCESS=record
dwProcessId:DWORD;
ProcessStartTime:FILETIME;
end;
RM_APP_TYPE=DWORD;
RM_PROCESS_INFO=record
Process:RM_UNIQUE_PROCESS;
strAppName:array[1..CCH_RM_MAX_APP_NAME+1] of Char;
strServiceShortName:array[1..CCH_RM_MAX_SVC_NAME+1] of Char;
ApplicationType:RM_APP_TYPE;
AppStatus:ULONG;
TSSessionId:DWORD;
bRestartable:BOOL;
end;
RM_WRITE_STATUS_CALLBACK=DWORD;
function RmStartSession(var pSessionHandle:DWORD;dwSessionFlags:DWORD;strSessionKey:SessionKey):DWORD;
external 'RmStartSession#Rstrtmgr.dll stdcall delayload';
function RmEndSession(dwSessionHandle:DWORD):DWORD;
external 'RmEndSession#Rstrtmgr.dll stdcall delayload';
function RmRegisterResources(dwSessionHandle:DWORD;hFiles:UINT;rgsFilenames:TArrayOfString;nApplications:UINT;rgApplications:array of RM_UNIQUE_PROCESS;nServices:UINT;rgsServiceNames:TArrayOfString):DWORD;
external 'RmRegisterResources#Rstrtmgr.dll stdcall delayload';
function RmGetList(dwSessionHandle:DWORD;var pnProcInfoNeeded,pnProcInfo:UINT;rgAffectedApps:array of RM_PROCESS_INFO;var lpdwRebootReasons:DWORD):DWORD;
external 'RmGetList#Rstrtmgr.dll stdcall delayload';
function RmShutdown(dwSessionHandle:DWORD;lActionFlags:ULONG;fnStatus:RM_WRITE_STATUS_CALLBACK):DWORD;
external 'RmShutdown#Rstrtmgr.dll stdcall delayload';
function RmRestart(dwSessionHandle:DWORD;dwRestartFlags:DWORD;fnStatus:RM_WRITE_STATUS_CALLBACK):DWORD;
external 'RmRestart#Rstrtmgr.dll stdcall delayload';
var
Processes: ProcessList;
RestartManagerHandle:DWORD;
{-------------------------------------------------------------------------}
{ Returns a list of running processes that currectly use one of the specified modules. }
{ Each module has to be a full path and filename to a DLL. }
function FindProcessesUsingModules(Modules:TArrayOfString;var Processes:ProcessList):DWORD;
var
Handle:DWORD;
Name:SessionKey;
Apps:array of RM_UNIQUE_PROCESS;
Services:TArrayOfString;
Path:String;
PathLength:DWORD;
Needed,Have,i:UINT;
AppList:array of RM_PROCESS_INFO;
RebootReason:DWORD;
Success:DWORD;
begin
SetArrayLength(Processes,0);
Result:=INVALID_HANDLE_VALUE;
{ NULL-terminate the array of chars. }
Name[CCH_RM_SESSION_KEY+1]:=#0;
if RmStartSession(Handle,0,Name)<>ERROR_SUCCESS then begin
Exit;
end;
if RmRegisterResources(Handle,GetArrayLength(Modules),Modules,0,Apps,0,Services)=ERROR_SUCCESS then begin
{ Reallocate the arrays until they are large enough to hold the process information. }
Needed:=1;
repeat
Have:=Needed;
SetArrayLength(AppList,Have);
Success:=RmGetList(Handle,Needed,Have,AppList,RebootReason);
until (Success<>ERROR_MORE_DATA) or (Have>=Needed);
if (Success=ERROR_SUCCESS) and (Needed>0) then begin
for i:=0 to Needed-1 do begin
{ append to end of list }
Have:=GetArrayLength(Processes);
SetArrayLength(Processes,Have+1);
{ assign values to new entry }
Processes[Have].ID:=AppList[i].Process.dwProcessId;
Processes[Have].Name:=ArrayToString(AppList[i].strAppName);
Processes[Have].Restartable:=AppList[i].bRestartable;
Processes[Have].ToTerminate:=True;
end;
Result:=Handle;
end;
end;
if (Result=INVALID_HANDLE_VALUE) then
RmEndSession(Handle);
end;
{-------------------------------------------------------------------------}
{ Returns a list of running processes that currectly use the specified module.
{ The module has to be a full path and filename to a DLL. This starts the }
{ RestartManager and returns its handle or INVALID_HANDLE_VALUE if failed }
{ or nothing has lock }
function FindProcessesUsingModule(Module:String;var Processes:ProcessList):DWORD;
var
Modules:TArrayOfString;
begin
SetArrayLength(Modules,1);
Modules[0]:=Module;
Result:=FindProcessesUsingModules(Modules,Processes);
end;
{-------------------------------------------------------------------------}
var
UninstallDelDataPage: TNewNotebookPage;
UninstallConfirmPage: TNewNotebookPage;
UninstallProcessListPage: TNewNotebookPage;
UninstallBackButton: TNewButton;
UninstallNextButton: TNewButton;
UninstallAutoCloseRB: TNewRadioButton;
DeleteAppDataCheckBox: TNewCheckBox;
AppData: String;
{-------------------------------------------------------------------------}
procedure UpdateUninstallWizard;
begin
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallDelDataPage then
begin
UninstallProgressForm.PageNameLabel.Caption := 'Select Data Uninstall Options';
UninstallProgressForm.PageDescriptionLabel.Caption := 'What data, if any, should be deleted?';
end
else
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallConfirmPage then
begin
UninstallProgressForm.PageNameLabel.Caption := 'Confirm Uninstall';
UninstallProgressForm.PageDescriptionLabel.Caption := 'Confirm the uninstall options below.';
end
else
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallProcessListPage then
begin
UninstallProgressForm.PageNameLabel.Caption := 'Preparing to Uninstall';
UninstallProgressForm.PageDescriptionLabel.Caption := 'Uninstall is preparing to uninstall {#MyAppName} from your computer.'
end;
UninstallBackButton.Visible :=
(UninstallProgressForm.InnerNotebook.ActivePage = UninstallConfirmPage) or
((UninstallProgressForm.InnerNotebook.ActivePage = UninstallDelDataPage) and (UninstallProcessListPage<>nil));
if (UninstallProgressForm.InnerNotebook.ActivePage = UninstallDelDataPage) or
((UninstallProgressForm.InnerNotebook.ActivePage = UninstallProcessListPage) and (UninstallDelDataPage<>nil)) then
begin
UninstallNextButton.Caption := SetupMessage(msgButtonNext);
UninstallNextButton.ModalResult := mrNone;
end
else
begin
UninstallNextButton.Caption := 'Uninstall';
{ Make the "Uninstall" button break the ShowModal loop }
UninstallNextButton.ModalResult := mrOK;
end;
end;
{-------------------------------------------------------------------------}
procedure CreateUninstallConfirmPage();
var
PageText: TNewStaticText;
begin
{ Create the second page }
if (UninstallConfirmPage<>nil) then UninstallConfirmPage.Free();
UninstallConfirmPage := TNewNotebookPage.Create(UninstallProgressForm);
UninstallConfirmPage.Notebook := UninstallProgressForm.InnerNotebook;
UninstallConfirmPage.Parent := UninstallProgressForm.InnerNotebook;
UninstallConfirmPage.Align := alClient;
PageText := TNewStaticText.Create(UninstallProgressForm);
PageText.Parent := UninstallConfirmPage;
PageText.Top := UninstallProgressForm.StatusLabel.Top;
PageText.Left := UninstallProgressForm.StatusLabel.Left;
PageText.Width := UninstallProgressForm.StatusLabel.Width;
PageText.Height := UninstallProgressForm.StatusLabel.Height;
PageText.AutoSize := True;
PageText.Wordwrap := True;
PageText.ShowAccelChar := False;
PageText.Font.Size := 9;
PageText.Caption := 'Click Uninstall to continue with removal of {#MyAppName}.';
if DeleteAppDataCheckBox.Checked then
PageText.Caption := PageText.Caption + #13#10#10 + 'WARNING: Application data will be deleted.';
end;
{-------------------------------------------------------------------------}
procedure UninstallNextButtonClick(Sender: TObject);
begin
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallConfirmPage then
begin
UninstallNextButton.Visible := False;
UninstallBackButton.Visible := False;
end
else
begin
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallDelDataPage then
begin
CreateUninstallConfirmPage();
UninstallProgressForm.InnerNotebook.ActivePage := UninstallConfirmPage;
end
else if UninstallDelDataPage<>nil then
begin
UninstallProgressForm.InnerNotebook.ActivePage := UninstallDelDataPage;
end
else
begin
UninstallNextButton.Visible := False;
UninstallBackButton.Visible := False;
end;
UpdateUninstallWizard;
end;
end;
{-------------------------------------------------------------------------}
procedure UninstallBackButtonClick(Sender: TObject);
begin
if UninstallProgressForm.InnerNotebook.ActivePage = UninstallConfirmPage then
begin
UninstallProgressForm.InnerNotebook.ActivePage := UninstallDelDataPage;
end
else if (UninstallProgressForm.InnerNotebook.ActivePage = UninstallDelDataPage) and (UninstallProcessListPage<>Nil) then
begin
UninstallProgressForm.InnerNotebook.ActivePage := UninstallProcessListPage;
end;
UpdateUninstallWizard;
end;
{-------------------------------------------------------------------------}
procedure InitializeUninstallProgressForm();
var
PageText: TNewStaticText;
PageNameLabel: string;
PageDescriptionLabel: string;
CancelButtonEnabled: Boolean;
CancelButtonModalResult: Integer;
appinstalled: Boolean;
top : Integer;
ListBox : TNewListBox;
i:Integer;
UninstallNoCloseRB : TNewRadioButton;
begin
RestartManagerHandle:=FindProcessesUsingModule(ExpandConstant('{app}\MyModule.dll'), Processes);
if not UninstallSilent then
begin
{ save labels / description }
PageNameLabel := UninstallProgressForm.PageNameLabel.Caption;
PageDescriptionLabel := UninstallProgressForm.PageDescriptionLabel.Caption;
if RestartManagerHandle<>INVALID_HANDLE_VALUE then
begin
UninstallProcessListPage:=TNewNotebookPage.Create(UninstallProgressForm);
UninstallProcessListPage.Notebook := UninstallProgressForm.InnerNotebook;
UninstallProcessListPage.Parent := UninstallProgressForm.InnerNotebook;
UninstallProcessListPage.Align := alClient;
PageText := TNewStaticText.Create(UninstallProgressForm);
PageText.Parent := UninstallProcessListPage;
PageText.Top := UninstallProgressForm.StatusLabel.Top;
PageText.Left := UninstallProgressForm.StatusLabel.Left;
PageText.Width := UninstallProgressForm.StatusLabel.Width;
PageText.Height := UninstallProgressForm.StatusLabel.Height;
PageText.AutoSize := True;
PageText.WordWrap := True;
PageText.ShowAccelChar := False;
PageText.Caption := 'The following applications are using files that need to be removed by the uninstaller. It is recommended that you allow Uninstall to automatically close these applications. After uninstall has completed, it will attempt to restart the applications.';
ListBox := TNewListBox.Create(UninstallProgressForm);
ListBox.Parent := UninstallProcessListPage;
ListBox.Top := PageText.Top + PageText.Height + 16;
ListBox.Left := PageText.Left;
ListBox.Width := PageText.Width;
ListBox.Height := ScaleY(97);
ListBox.TabStop:=False;
for i:=0 to GetArraylength(Processes)-1 do
begin
ListBox.Items.Add(Processes[i].Name);
end;
ListBox.ItemIndex:=-1;
UninstallAutoCloseRB := TNewRadioButton.Create(UninstallProgressForm);
UninstallAutoCloseRB .Parent := UninstallProcessListPage;
UninstallAutoCloseRB .Checked := True;
UninstallAutoCloseRB .Top := ListBox.Top+ListBox.Height+8;
UninstallAutoCloseRB .Left := ListBox.Left;
UninstallAutoCloseRB .Width := ListBox.Width;
UninstallAutoCloseRB.Font.Size := 9;
UninstallAutoCloseRB.Caption := '&Automatically close the applications';
UninstallNoCloseRB := TNewRadioButton.Create(UninstallProgressForm);
UninstallNoCloseRB .Parent := UninstallProcessListPage;
UninstallNoCloseRB .Checked := False;
UninstallNoCloseRB .Top := UninstallAutoCloseRB.Top+UninstallAutoCloseRB.Height+8;
UninstallNoCloseRB .Left := UninstallAutoCloseRB.Left;
UninstallNoCloseRB .Width := UninstallAutoCloseRB.Width;
UninstallNoCloseRB .Font.Size := 9;
UninstallNoCloseRB .Caption := '&Do not close the applications';
{ make page active }
UninstallProgressForm.InnerNotebook.ActivePage := UninstallProcessListPage;
end;
{ work around elevated uninstaller for single user}
AppData:=GetEnv('AppData');
Log('AppData reported as' + AppData);
if AppData<>'' then
begin
appinstalled:=FileExists(ExpandConstant('{app}/myapp.exe'));
if appinstalled then
begin
{ Create the first page and make it active }
UninstallDelDataPage := TNewNotebookPage.Create(UninstallProgressForm);
UninstallDelDataPage.Notebook := UninstallProgressForm.InnerNotebook;
UninstallDelDataPage.Parent := UninstallProgressForm.InnerNotebook;
UninstallDelDataPage.Align := alClient;
PageText := TNewStaticText.Create(UninstallProgressForm);
PageText.Parent := UninstallDelDataPage;
PageText.Top := UninstallProgressForm.StatusLabel.Top;
PageText.Left := UninstallProgressForm.StatusLabel.Left;
PageText.Width := UninstallProgressForm.StatusLabel.Width;
PageText.Height := UninstallProgressForm.StatusLabel.Height;
PageText.AutoSize := True;
PageText.WordWrap := True;
PageText.ShowAccelChar := False;
PageText.Caption := 'You have the option to delete the data assoicated with App Name';
top:=PageText.Top + PageText.Height + 16;
if appinstalled then
begin
DeleteAppDataCheckBox := TNewCheckBox.Create(UninstallProgressForm);
DeleteAppDataCheckBox.Parent := UninstallDelDataPage;
DeleteAppDataCheckBox.Checked := False;
DeleteAppDataCheckBox.Top := top;
DeleteAppDataCheckBox.Left := PageText.Left+10;
DeleteAppDataCheckBox.Width := PageText.Width - 10;
DeleteAppDataCheckBox.Font.Size := 9;
DeleteAppDataCheckBox.Caption := 'Delete all App Data';
top:=DeleteAppDataCheckBox.Top + DeleteAppDataCheckBox.Height + 8;
end;
{ set as first page if not already set }
if UninstallProgressForm.InnerNotebook.ActivePage=UninstallProgressForm.InstallingPage then
UninstallProgressForm.InnerNotebook.ActivePage:=UninstallDelDataPage;
{ next button }
UninstallNextButton := TNewButton.Create(UninstallProgressForm);
UninstallNextButton.Parent := UninstallProgressForm;
UninstallNextButton.Left := UninstallProgressForm.CancelButton.Left - UninstallProgressForm.CancelButton.Width - ScaleX(10);
UninstallNextButton.Top := UninstallProgressForm.CancelButton.Top;
UninstallNextButton.Width := UninstallProgressForm.CancelButton.Width;
UninstallNextButton.Height := UninstallProgressForm.CancelButton.Height;
UninstallNextButton.OnClick := #UninstallNextButtonClick;
{ back button }
UninstallBackButton := TNewButton.Create(UninstallProgressForm);
UninstallBackButton.Parent := UninstallProgressForm;
UninstallBackButton.Left := UninstallNextButton.Left - UninstallNextButton.Width - ScaleX(10);
UninstallBackButton.Top := UninstallProgressForm.CancelButton.Top;
UninstallBackButton.Width := UninstallProgressForm.CancelButton.Width;
UninstallBackButton.Height := UninstallProgressForm.CancelButton.Height;
UninstallBackButton.Caption := SetupMessage(msgButtonBack);
UninstallBackButton.OnClick := #UninstallBackButtonClick;
{ setup tab order }
UninstallBackButton.TabOrder := UninstallProgressForm.CancelButton.TabOrder;
UninstallNextButton.TabOrder := UninstallBackButton.TabOrder + 1;
UninstallProgressForm.CancelButton.TabOrder := UninstallNextButton.TabOrder + 1;
{ Run our wizard pages }
UpdateUninstallWizard;
CancelButtonEnabled := UninstallProgressForm.CancelButton.Enabled
UninstallProgressForm.CancelButton.Enabled := True;
{ save value }
CancelButtonModalResult := UninstallProgressForm.CancelButton.ModalResult;
{ set value to use }
UninstallProgressForm.CancelButton.ModalResult := mrCancel;
if UninstallProgressForm.ShowModal = mrCancel then
begin
if RestartManagerHandle<>INVALID_HANDLE_VALUE then
begin
RmEndSession(RestartManagerHandle);
RestartManagerHandle:=INVALID_HANDLE_VALUE;
end;
Abort;
end;
{ Restore the standard page payout }
UninstallProgressForm.CancelButton.Enabled := CancelButtonEnabled;
UninstallProgressForm.CancelButton.ModalResult := CancelButtonModalResult;
UninstallProgressForm.PageNameLabel.Caption := PageNameLabel;
UninstallProgressForm.PageDescriptionLabel.Caption := PageDescriptionLabel;
UninstallProgressForm.InnerNotebook.ActivePage := UninstallProgressForm.InstallingPage;
end;
end;
end;
end;
{-------------------------------------------------------------------------}
function IsDeleteAppData: Boolean;
begin
Result:=(DeleteAppDataCheckBox<>nil) and DeleteAppDataCheckBox.Checked;
end;
{-------------------------------------------------------------------------}
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
ErrorCode: Integer;
Res : Boolean;
begin
if CurUninstallStep = usUninstall then
begin
if (RestartManagerHandle<>INVALID_HANDLE_VALUE) and (UninstallAutoCloseRB<>nil) and (UninstallAutoCloseRB.Checked) then
RmShutdown(RestartManagerHandle, 0, 0);
end
else if CurUninstallStep = usPostUninstall then
begin
if IsDeleteAppData then
begin
Res:=DelTree(AppData+'\MyAppDataDir', true, true, true);
Log('Delete '+AppData+'\MyAppDataDir result: '+IntToStr(Integer(Res)));
end;
if (RestartManagerHandle<>INVALID_HANDLE_VALUE) and (UninstallAutoCloseRB<>nil) and (UninstallAutoCloseRB.Checked) then
RmRestart(RestartManagerHandle, 0, 0);
if (RestartManagerHandle<>INVALID_HANDLE_VALUE) then
begin
RmEndSession(RestartManagerHandle);
RestartManagerHandle:=INVALID_HANDLE_VALUE;
end;
end;
end;
This is the code with the error:
#include "Music\botva2.iss"
#include "Music\BASS_Module.iss"
[Code]
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
external 'ShellExecuteW#shell32.dll stdcall';
var
LanguageForm: TSetupForm;
SelectLabel: TNewStaticText;
CancelButton: TNewButton;
procedure LangChange(Sender : TObject);
begin
case TNewComboBox(Sender).ItemIndex of
0: { English }
begin
SelectLabel.Caption := 'Select the language to the installation:';
CancelButton.Caption := 'Cancel';
LanguageForm.Caption := 'PH';
end;
1: { Español }
begin
SelectLabel.Caption := 'Selecciona el idioma de la instalación:';
CancelButton.Caption := 'Cancelar';
LanguageForm.Caption := 'PH';
end;
end;
end;
procedure SelectLanguage();
var
OKButton: TNewButton;
LangCombo: TNewComboBox;
Languages: TStrings;
Params: string;
Instance: THandle;
P, I: Integer;
S, L: string;
begin
Languages := TStringList.Create();
Languages.Add('eng=English');
Languages.Add('spa=Español');
LanguageForm := CreateCustomForm;
LanguageForm.Caption := SetupMessage(msgSelectLanguageTitle);
LanguageForm.ClientWidth := ScaleX(240);
LanguageForm.ClientHeight := ScaleY(125);
LanguageForm.BorderStyle := bsDialog;
LanguageForm.Center;
CancelButton := TNewButton.Create(LanguageForm);
CancelButton.Parent := LanguageForm;
CancelButton.Left := ScaleX(140);
CancelButton.Top := ScaleY(93);
CancelButton.Width := ScaleY(90);
CancelButton.Height := ScaleY(23);
CancelButton.TabOrder := 3;
CancelButton.ModalResult := mrCancel;
CancelButton.Caption := SetupMessage(msgButtonCancel);
OKButton := TNewButton.Create(LanguageForm);
OKButton.Parent := LanguageForm;
OKButton.Left := ScaleX(10);
OKButton.Top := ScaleY(93);
OKButton.Width := ScaleX(90);
OKButton.Height := ScaleY(23);
OKButton.Caption := SetupMessage(msgButtonOK);
OKButton.Default := True
OKButton.ModalResult := mrOK;
OKButton.TabOrder := 2;
LangCombo := TNewComboBox.Create(LanguageForm);
LangCombo.Parent := LanguageForm;
LangCombo.Left := ScaleX(16);
LangCombo.Top := ScaleY(56);
LangCombo.Width := ScaleX(206);
LangCombo.Height := ScaleY(21);
LangCombo.Style := csDropDownList;
LangCombo.DropDownCount := 16;
LangCombo.TabOrder := 1;
SelectLabel := TNewStaticText.Create(LanguageForm);
SelectLabel.Parent := LanguageForm;
SelectLabel.Left := ScaleX(16);
SelectLabel.Top := ScaleY(15);
SelectLabel.Width := ScaleX(273);
SelectLabel.Height := ScaleY(39);
SelectLabel.AutoSize := False
SelectLabel.Caption := SetupMessage(msgSelectLanguageLabel);
SelectLabel.TabOrder := 0;
SelectLabel.WordWrap := True;
for I := 0 to Languages.Count - 1 do
begin
P := Pos('=', Languages.Strings[I]);
L := Copy(Languages.Strings[I], 0, P - 1);
S := Copy(Languages.Strings[I], P + 1, Length(Languages.Strings[I]) - P);
LangCombo.Items.Add(S);
if L = ActiveLanguage then
LangCombo.ItemIndex := I;
LangCombo.OnChange := #LangChange;
end;
if LanguageForm.ShowModal = mrOK then
begin
// Collect current instance parameters
for I := 1 to ParamCount do
begin
S := ParamStr(I);
// Unique log file name for the elevated instance
if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then
begin
S := S + '-localized';
end;
// Do not pass our /SL5 switch
if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then
begin
Params := Params + AddQuotes(S) + ' ';
end;
end;
L := Languages.Strings[LangCombo.ItemIndex];
P := Pos('=', L);
L := Copy(L, 0, P-1);
// ... and add selected language
Params := Params + '/LANG=' + L;
Instance := ShellExecute(0, '', ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
if Instance <= 32 then
begin
MsgBox(
Format('Running installer with selected language failed. Code: %d', [Instance]),
mbError, MB_OK);
end;
end;
end;
function InitializeSetup(): Boolean;
var
Language: string;
begin
Result := True;
Language := ExpandConstant('{param:LANG}');
if Language = '' then
begin
Log('No language specified, showing language dialog');
SelectLanguage();
Result := False;
Exit;
end
else
begin
Log('Language specified, proceeding with installation');
end;
end;
procedure RedesignWizardForm;
begin
with WizardForm do
begin
BorderIcons:=[];
Bevel1.Hide;
AutoScroll := False;
ClientHeight := ScaleY(349);
end;
with WizardForm.CancelButton do
begin
Top := ScaleY(319);
end;
with WizardForm.NextButton do
begin
Top := ScaleY(319);
end;
with WizardForm.BackButton do
begin
Top := ScaleY(319);
end;
with WizardForm.WizardBitmapImage do
begin
Width := ScaleX(500);
end;
with WizardForm.WelcomeLabel2 do
begin
Visible := False;
end;
with WizardForm.WelcomeLabel1 do
begin
Visible := False;
end;
with WizardForm.WizardSmallBitmapImage do
begin
Left := ScaleX(0);
Width := ScaleX(500);
Height := ScaleY(60);
end;
with WizardForm.PageDescriptionLabel do
begin
Visible := False;
end;
with WizardForm.PageNameLabel do
begin
Visible := False;
end;
with WizardForm.WizardBitmapImage2 do
begin
Width := ScaleX(500);
ExtractTemporaryFile('WizardForm.WizardBitmapImage2.bmp');
Bitmap.LoadFromFile(ExpandConstant('{tmp}\WizardForm.WizardBitmapImage2.bmp'));
end;
with WizardForm.FinishedLabel do
begin
Visible := False;
end;
with WizardForm.FinishedHeadingLabel do
begin
Visible := False;
end;
end;
procedure InitializeWizard1();
begin
RedesignWizardForm;
WizardForm.DiskSpaceLabel.Visible := False;
end;
procedure InitializeWizard2();
begin
ExtractTemporaryFile('BASS.dll');
ExtractTemporaryFile('CallbackCtrl.dll');
ExtractTemporaryFile('botva2.dll');
ExtractTemporaryFile('MusicButton.png');
ExtractTemporaryFile('Music.mp3');
BASS_Init('{tmp}\Music.mp3')
BASS_CreateOnOffButton(WizardForm, '{tmp}\MusicButton.png', 20, 320, 36, 36, 4)
end;
procedure InitializeWizard();
begin
InitializeWizard1();
InitializeWizard2();
end;
procedure DeinitializeSetup();
begin
BASS_DeInit; //Îñâîáîæäàåì ïðîöåññ
gdipShutdown
end;
This code includes the language selector Inno Setup - How to change a label caption [or other controls in general], when selected value in combox box changes and a code that define music and music button. If i delete all about language selector, the code works fine. What is the problem?
The code of music and button includes: botva2.iss, BASS_Module.iss, botva2.dll, CallbackCtrl.dll.
This error appears when you select accept or cancel on the language selector.
The DeinitializeSetup is called, even when the setup is aborted by returning False from the InitializeSetup.
So I guess the BASS_DeInit (or the gdipShutdown) fails, because an equivalent BASS_Init was never called.
You have to avoid calling the code in the DeinitializeSetup, when the BASS_Init was never called.
var
BASS_Initialized: Boolean;
procedure InitializeWizard2();
begin
ExtractTemporaryFile('BASS.dll');
ExtractTemporaryFile('CallbackCtrl.dll');
ExtractTemporaryFile('botva2.dll');
ExtractTemporaryFile('MusicButton.png');
ExtractTemporaryFile('Music.mp3');
BASS_Init('{tmp}\Music.mp3')
BASS_CreateOnOffButton(WizardForm, '{tmp}\MusicButton.png', 20, 320, 36, 36, 4);
BASS_Initialized := True;
end;
procedure DeinitializeSetup();
begin
if BASS_Initialized then
begin
BASS_DeInit;
gdipShutdown;
end;
end;
can anyone tell me how to connect to SQL 2008 using windows authentication thru inno? Currently I'm using ado connection to connect to SQL from inno, the user needs windows authentication option too. Please suggest.
It's enough to remove the credential attributes from your connection string (User Id and Password) when we are talking about the example you've linked in your question and include one of the following:
Integrated Security=SSPI;
Trusted_Connection=True;
This answer is based just on this topic, I haven't tested it.
Update:
I don't know if that's what you want to do, but I'll post it here. The following script creates a custom page with radio buttons letting user choose authentication mode and optionally fill the credentials.
Important:
There is no protection against SQL injection for those credential fields!
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
LT_WindowsAuthentication = 0;
LT_SQLServerAuthentication = 1;
var
LoginType: Integer;
UsernameEdit: TNewEdit;
UsernameLabel: TLabel;
PasswordEdit: TNewEdit;
PasswordLabel: TLabel;
procedure OnLoginTypeChange(Sender: TObject);
var
EditColor: TColor;
LabelColor: TColor;
begin
LoginType := TNewRadioButton(Sender).Tag;
UsernameEdit.Enabled := LoginType = LT_SQLServerAuthentication;
PasswordEdit.Enabled := LoginType = LT_SQLServerAuthentication;
case LoginType of
LT_WindowsAuthentication:
begin
EditColor := clBtnFace;
LabelColor := clGray;
end;
LT_SQLServerAuthentication:
begin
EditColor := clWindow;
LabelColor := clBlack;
end;
end;
UsernameEdit.Color := EditColor;
PasswordEdit.Color := EditColor;
UsernameLabel.Font.Color := LabelColor;
PasswordLabel.Font.Color := LabelColor;
end;
procedure InitializeWizard;
var
LoginPage: TWizardPage;
begin
LoginPage := CreateCustomPage(wpWelcome, 'DB Login', 'Choose a login type to continue...');
with TNewRadioButton.Create(WizardForm) do
begin
Parent := LoginPage.Surface;
Left := 0;
Top := 0;
Width := LoginPage.Surface.ClientWidth;
Checked := True;
Tag := 0;
Caption := 'Windows authentication';
OnClick := #OnLoginTypeChange;
end;
with TNewRadioButton.Create(WizardForm) do
begin
Parent := LoginPage.Surface;
Left := 0;
Top := 20;
Width := LoginPage.Surface.ClientWidth;
Checked := False;
Tag := 1;
Caption := 'SQL Server authentication';
OnClick := #OnLoginTypeChange;
end;
UsernameLabel := TLabel.Create(WizardForm);
with UsernameLabel do
begin
Parent := LoginPage.Surface;
Left := 12;
Top := 44;
Width := 200;
Font.Color := clGray;
Font.Style := [fsBold];
Caption := 'Username';
end;
UsernameEdit := TNewEdit.Create(WizardForm);
with UsernameEdit do
begin
Parent := LoginPage.Surface;
Left := 12;
Top := UsernameLabel.Top + UsernameLabel.Height + 6;
Width := 200;
Color := clBtnFace;
Enabled := False;
end;
PasswordLabel := TLabel.Create(WizardForm);
with PasswordLabel do
begin
Parent := LoginPage.Surface;
Left := 12;
Top := UsernameEdit.Top + UsernameEdit.Height + 6;
Width := 200;
Font.Color := clGray;
Font.Style := [fsBold];
Caption := 'Password';
end;
PasswordEdit := TNewEdit.Create(WizardForm);
with PasswordEdit do
begin
Parent := LoginPage.Surface;
Left := 12;
Top := PasswordLabel.Top + PasswordLabel.Height + 6;
Width := 200;
Color := clBtnFace;
Enabled := False;
PasswordChar := '*';
end;
end;
// and in your connection event then use
case LoginType of
LT_WindowsAuthentication:
ADOConnection.ConnectionString :=
'Provider=SQLOLEDB;' + // provider
'Data Source=Default\SQLSERVER;' + // server name
'Initial Catalog=Northwind;' + // default database
'Integrated Security=SSPI;'; // trusted connection
LT_SQLServerAuthentication:
ADOConnection.ConnectionString :=
'Provider=SQLOLEDB;' + // provider
'Data Source=Default\SQLSERVER;' + // server name
'Initial Catalog=Northwind;' + // default database
'User Id=' + UsernameEdit.Text + ';' + // user name
'Password=' + PasswordEdit.Text + ';'; // password
end;
I am making use of Inno Setup (it's amazing!). I was hoping to customise the installer so that I can accept a string from the user in the form of an input field and maybe add a message to it.
How can I do this? I had a look through the docs, google search and not much came up!
Thanks all for any help
You can use Pascal scripting in InnoSetup to create new pages for the installer. These pages can be integrated into the normal installation flow. This is well documented within the InnoSetup documentation (Google search should also come up with samples). Also the Samples folder within your Program Files\InnoSetup has some code examples.
Some time ago, there was a software called InnoSetup Form designer, which allowed you to visually design the page. The link is still there, but on the page I could not find the download. Maybe if you look around a bit you can find it?
EDIT
This is a sample for a page I made once. This is the code section of the ISS file.[Code]
var
EnableFolderPage: Boolean;
lblBlobFileFolder: TLabel;
lblBlobFileWarning1: TLabel;
lblBlobFileWarning2: TLabel;
tbBlobFileFolder: TEdit;
btnBlobFileFolder: TButton;
function GetBlobFolder(param: String): String;
begin
Result := Trim(tbBlobFileFolder.Text);
end;
{ BlobFileForm_Activate }
procedure BlobFileForm_Activate(Page: TWizardPage);
var
s: string;
begin
s := Trim(tbBlobFileFolder.Text);
if (s = '') then
begin
tbBlobFileFolder.Text := ExpandConstant('{sys}');
end;
end;
{ BlobFileForm_NextButtonClick }
function BlobFileForm_NextButtonClick(Page: TWizardPage): Boolean;
var
s: string;
begin
s := Trim(tbBlobFileFolder.Text);
if (s = '') then
begin
MsgBox(ExpandConstant('{cm:BlobFileForm_NoFolder}'), mbError, MB_OK);
Result := false;
end else
begin
if not DirExists(s) then
begin
MsgBox(ExpandConstant('{cm:BlobFileForm_DirDoesntExist}'), mbError, MB_OK);
Result := false;
end else
begin
Result := True;
end;
end;
end;
procedure btnBlobFileFolder_Click(sender: TObject);
var
directory: string;
begin
if BrowseForFolder('', directory, true) then
begin
tbBlobFileFolder.Text := directory;
end;
end;
{ BlobFileForm_CreatePage }
function BlobFileForm_CreatePage(PreviousPageId: Integer): Integer;
var
Page: TWizardPage;
begin
Page := CreateCustomPage(
PreviousPageId,
ExpandConstant('{cm:BlobFileForm_Caption}'),
ExpandConstant('{cm:BlobFileForm_Description}')
);
{ lblBlobFileFolder }
lblBlobFileFolder := TLabel.Create(Page);
with lblBlobFileFolder do
begin
Parent := Page.Surface;
Caption := ExpandConstant('{cm:BlobFileForm_lblBlobFileFolder_Caption0}');
Left := ScaleX(8);
Top := ScaleY(8);
Width := ScaleX(167);
Height := ScaleY(13);
end;
{ lblBlobFileWarning1 }
lblBlobFileWarning1 := TLabel.Create(Page);
with lblBlobFileWarning1 do
begin
Parent := Page.Surface;
Caption := ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning1_Caption0}');
Left := ScaleX(8);
Top := ScaleY(80);
Width := ScaleX(50);
Height := ScaleY(13);
Font.Color := -16777208;
Font.Height := ScaleY(-11);
Font.Name := 'Tahoma';
Font.Style := [fsBold];
end;
{ lblBlobFileWarning2 }
lblBlobFileWarning2 := TLabel.Create(Page);
with lblBlobFileWarning2 do
begin
Parent := Page.Surface;
Caption :=
ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning2_Caption0}') + #13 +
ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning2_Caption1}') + #13 +
ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning2_Caption2}') + #13 +
ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning2_Caption3}') + #13 +
ExpandConstant('{cm:BlobFileForm_lblBlobFileWarning2_Caption4}');
Left := ScaleX(8);
Top := ScaleY(96);
Width := ScaleX(399);
Height := ScaleY(133);
AutoSize := False;
WordWrap := True;
end;
{ tbBlobFileFolder }
tbBlobFileFolder := TEdit.Create(Page);
with tbBlobFileFolder do
begin
Parent := Page.Surface;
Left := ScaleX(8);
Top := ScaleY(24);
Width := ScaleX(401);
Height := ScaleY(21);
TabOrder := 0;
end;
{ btnBlobFileFolder }
btnBlobFileFolder := TButton.Create(Page);
with btnBlobFileFolder do
begin
Parent := Page.Surface;
Caption := ExpandConstant('{cm:BlobFileForm_btnBlobFileFolder_Caption0}');
Left := ScaleX(320);
Top := ScaleY(48);
Width := ScaleX(91);
Height := ScaleY(23);
TabOrder := 1;
end;
with Page do
begin
OnActivate := #BlobFileForm_Activate;
OnNextButtonClick := #BlobFileForm_NextButtonClick;
end;
with btnBlobFileFolder do
begin
OnClick := #btnBlobFileFolder_Click;
end;
Result := Page.ID;
end;
procedure InitializeWizard();
begin
BlobFileForm_CreatePage(wpSelectDir);
end;
EDIT 2
To write the value the user entered to a registry key, create a new function:
function GetUserEnteredText(param: String): String;
begin
Result := Trim(tbTextBox.Text);
end;
This function simply returns what was entered in the text box. Please note that the function must take a string parameter - even though you ignore it!
In the [Registry] section of your script, declare the key that should be written like that:
Root: HKLM; Subkey: SOFTWARE\MyCompany\MyTool; ValueType: string; ValueName: MyValue; ValueData: {code:GetUserEnteredText}; Flags: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue
This creates a registry value named "MyValue" in HKLM\SOFTWARE\MyCompany\MyTool that contains what the user entered in the text box.
Here is shorter code to add a custom page to Inno Setup installer with an Input Field:
var
CustomQueryPage: TInputQueryWizardPage;
procedure AddCustomQueryPage();
begin
CustomQueryPage := CreateInputQueryPage(
wpWelcome,
'Custom message',
'Custom description',
'Custom instructions');
{ Add items (False means it's not a password edit) }
CustomQueryPage.Add('Custom Field:', False);
end;
procedure InitializeWizard();
begin
AddCustomQueryPage();
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
{ Read custom value }
MsgBox('Custom Value = ' + CustomQueryPage.Values[0], mbInformation, MB_OK);
end;
end;