wpSelectTasks: List index out of bounds (-1) when going back

234 views
Skip to first unread message

Niek

unread,
Apr 7, 2021, 9:49:24 AM4/7/21
to innosetup
Hello,

I have some code to check some components and set tasks checked or unchecked.
I also set the ItemCaption (I want to show user custom caption why my code deselected it), it works as intended on the wpSelectTasks page. But if I press back (so returning to wpSelectTasks) I am getting a "List index out of bounds (-1)"

I am using a LookupTask function to find out the index by name:

function LookupTask(TaskCustomMessage: string): Integer;
var
  Description: string;
begin
  Description := CustomMessage(TaskCustomMessage);
  Result := WizardForm.TasksList.Items.IndexOf(Description);
  Log(Format('Index of "%s" task is %d', [Description, Result]));
end;

[15:39:15,041]   Index of "MySQL Installer Utility" task is 1
[15:39:15,107]   Index of "MySQL Server 8.0.23 x64" task is 2
[15:39:15,154]   Index of "Create databases" task is 3

Pressing back:
[15:39:18,842]   Index of "MySQL Installer Utility" task is 1
[15:39:18,851]   Index of "MySQL Server 8.0.23 x64" task is -1
[15:39:18,863]   Index of "Create databases" task is 3

[15:39:37,204]   Exception message:
[15:39:37,218]   Message box (OK):
   Runtime error (at 83:8564):
   
   List index out of bounds (-1)

I do not understand why after pressing back the index is -1

Code:

    if CurPageID = wpSelectTasks then
    begin
    //If no component related to task is selected, then there is nothing to check and tasks will not be shown.
    if WizardIsComponentSelected('MySQL\MySQLInstaller\MySQLServer') then
    begin
      //Lookup TasksList index. This can differ if amount of tasks is changed.
      MySQLInstallerIndex := LookupTask('MySQLInstaller');
      MySQLServerIndex := LookupTask('MySQLServer');
      MySQLConfigureIndex := LookupTask('MySQLConfigure');
      //Always check MySQLInstaller utility task. It is ignored anyway if already installed.
      WizardForm.TasksList.Checked[MySQLInstallerIndex] := True;
        //Check if any MySQL Server keys are there. Registry keys are in WOW6432Node. Installer is 32-bit so auto will work.
        if not RegKeyExists(HKEY_AUTO, 'SOFTWARE\MySQL AB\MySQL Server 8.0') and not RegKeyExists(HKEY_AUTO, 'SOFTWARE\MySQL AB\MySQL Server 5.7') then
          begin
            Log('RegKeyExists is false. MySQL Server 5.7 and MySQL Server 8.0 are not found in registry');
            //MsgBox('RegKey not exist', mbInformation, MB_OK);
            //Set caption of dynamic index.
            WizardForm.TasksList.ItemCaption[MySQLServerIndex] := 'MySQL Server' + #13#10 + 'No existing MySQL Server installations found';
            //Check TasksList checkboxes because no MySQL detected.
            WizardForm.TasksList.Checked[MySQLServerIndex] := True;
            WizardForm.TasksList.Checked[MySQLConfigureIndex] := True;
          end
        else
          begin
            Log('RegKeyExists is true. MySQL Server 5.7 or MySQL Server 8.0 are found in registry');
            //MsgBox('RegKeyExist', mbInformation, MB_OK);
              //First check for MySQL 8.
              if RegQueryStringValue(HKEY_AUTO, 'SOFTWARE\MySQL AB\MySQL Server 8.0', 'Version', MysqlVersion) then
                begin
                  //MySQL 8 is found.
                  Log(Format('RegKeyExist for MySQL 8: Version=%s', [MysqlVersion]));
                  //MsgBox('MysqlVersion: ' + MysqlVersion, mbInformation, MB_OK);
                  //Set caption of dynamic index.
                  WizardForm.TasksList.ItemCaption[MySQLServerIndex] := 'MySQL Server' + #13#10 + 'Unchecked because already installed MySQL Server version ' + MysqlVersion + ' found!';
                  //UNcheck TasksList checkboxes because MySQL detected.
                  WizardForm.TasksList.Checked[MySQLServerIndex] := False;
                  WizardForm.TasksList.Checked[MySQLConfigureIndex] := False;
                end

Can anybody explain what is different to the wpSelectTasks the second time?

Greetings!
Niek

Niek

unread,
Apr 7, 2021, 4:21:53 PM4/7/21
to innosetup
Ok, I found out why the index is missing. Logical reason.
On first load I change the description of the TasksList entry and the LookupTask looks up the index by using the description I set trough a custommessage.
So when going back I the description is changed and the comparison fails.

Hardcoding index number is a workaround, but I rather would like to avoid that. Anybody with a good idea?





Op woensdag 7 april 2021 om 15:49:24 UTC+2 schreef Niek:

Gavin Lambert

unread,
Apr 7, 2021, 5:55:00 PM4/7/21
to inno...@googlegroups.com
On 8/04/2021 8:21 am, Niek wrote:
> Ok, I found out why the index is missing. Logical reason.
> On first load I change the description of the TasksList entry and the
> LookupTask looks up the index by using the description I set trough a
> custommessage.
> So when going back I the description is changed and the comparison fails.
>
> Hardcoding index number is a workaround, but I rather would like to
> avoid that. Anybody with a good idea?

You could lookup and save the indexes into variables on first load.

Or use separate [Tasks] conditioned via Check rather than changing the
description at runtime. (Though you may need to be careful with timing,
depending on what you're checking.)

Niek

unread,
Apr 8, 2021, 2:40:27 AM4/8/21
to innosetup
Hi Gavin,

Yes saving them would be best approach. But how to save them only on first load? Because the indexes only exist on the TaskPage I use the CurPageChanged procedure which runs every time you change to that page.
How could I save the variables in that procedure only once?

Op woensdag 7 april 2021 om 23:55:00 UTC+2 schreef Gavin Lambert:

Gavin Lambert

unread,
Apr 8, 2021, 3:03:08 AM4/8/21
to inno...@googlegroups.com
On 8/04/2021 6:40 pm, Niek wrote:
> Yes saving them would be best approach. But how to save them only on
> first load? Because the indexes only exist on the TaskPage I use the
> CurPageChanged procedure which runs every time you change to that page.
> How could I save the variables in that procedure only once?

Well, the obvious method is: do it only once!

(You can just check if you've saved the indexes yet; if they're not set
yet then you obviously haven't done it yet, otherwise you have.)

Having said that, you don't need to wait that long. Unless it's been
changed since the last time I checked, all of the tasks are populated
prior to InitializeWizard, so you can just do it there instead.

Niek

unread,
Apr 8, 2021, 3:43:43 AM4/8/21
to innosetup
Thank you Gavin, but I don't think the tasks are populated in InitializeWizard. Using them there all give -1.

If you try to update the TasksList in the InitializeWizard, you must get the exception as at that point the TasksList is not populated yet, no matter if the tasks are conditional or not.
The TasksList is populated only once you move to the "Select Additional Tasks" page.


Op donderdag 8 april 2021 om 09:03:08 UTC+2 schreef Gavin Lambert:

Niek

unread,
Apr 8, 2021, 5:26:35 AM4/8/21
to innosetup
Ok, I just add a if not (MySQLServerIndex = -1) then begin
Which skips if the index cannot be determined.

Op donderdag 8 april 2021 om 09:43:43 UTC+2 schreef Niek:
Reply all
Reply to author
Forward
0 new messages