Is there a way to programmatically retrieve a list of all components which were added to the project?

To verify my component packaging and runtime-selection logic, I'd like to be able to display a list of all components, and some of their properties (e.g. whether they are enabled or disabled).

asked 23 May '13, 06:42

Dirk%20Stegemann's gravatar image

Dirk Stegemann
681283244
accept rate: 31%


With a list of all components, I had hoped to write a function that iterates over all packed components, and logs some of their properties.

Something like this:

<foreach variables="currentComponent" values="${listOfAllComponents}">
    <actionList>
        <logMessage text="${currentComponent.name}.description: '${currentComponent.description}'" />
        <logMessage text="${currentComponent.name}.canBeEdited: '${currentComponent.canBeEdited}'" />
        <logMessage text="${currentComponent.name}.selected:    '${currentComponent.selected}'" />
        <logMessage text="${currentComponent.name}.show:        '${currentComponent.show}'" />
    </actionList>
</foreach>

I helped myself by adding a similar code into each component's <initializationActionList>:

<component>
    <initializationActionList>
        <logMessage text="<hard-coded component name>.selected: '${component(<hard-coded component name>).selected}'" />
    </initializationActionList>
    ...
<component>

Which raises the new question: is it possible to reference a component's attributes from within the component's actionLists without having to refer to its name?

It would be nicer to have something generic like

<component>
    <initializationActionList>
        <logMessage text="THIS.selected: '${component(THIS).selected}'" />
    </initializationActionList>
    ...
<component>
link

answered 27 May '13, 10:49

Dirk%20Stegemann's gravatar image

Dirk Stegemann
681283244
accept rate: 31%

Yes! Upon my initial implementation of our installer, I found several places where "THIS" would've been the ideal solution.

(29 May '13, 04:06) DevHopeful_2012

It is not currently possible to programatically list them. Do you have a very big number of components? Are they distributed in multiple files? Are you using componentGroups?

link

answered 27 May '13, 09:45

juanjo's gravatar image

juanjo ♦♦
5.8k413
accept rate: 23%

See long comment below...

(27 May '13, 10:49) Dirk Stegemann

We required the same functionality, but, to go a bit further, certain components were platform-specific and we wanted to know if the component was selected/deselected after the user's selection. So, as a workaround, I wrote the below custom function which is called in the installer's initializationActionList. Then, the UI can use this list to iterate over, in order to determine what is selected at any given time. Of course, this requires an updated list of all possible components, so it isn't the most ideal solution.

<!--
        getComponentLists

        parameters:
            None

        return values:
            all_components_list - all component names

            select_all_components_list - comma separated version of the
            all_components_list for selection/deselection

        Notes:  This function is for grouping components into lists that can be
        used for the installer summary, resetting default selections, and toggling
        the visibility for different views.  Due to the fact that some components
        may be platform-specific and are not packed, this is a non-trivial task.

        Remember to leave whitespace after the last element of any of the lists.
        Otherwise, if the last element is not packed, the regex will not correctly
        remove it from the list.
    -->
    <actionDefinition>
        <name>getComponentLists</name>
        <actionList>
            <!-- Initialize list with all possible components -->
            <setInstallerVariable name="all_components_list">
                <value>core project.component(core)
    foo project.component(foo)
    bar project.component(bar)
    samples_linux_only project.component(samples).component(linux_only)
    mac_only project.component(samples).component(mac_only)
    </value>
            </setInstallerVariable>
            <!-- Loop to see which components exist -->
            <foreach>
                <values>${all_components_list}</values>
                <variables>component_name full_component_name</variables>
                <actionList>
                    <!-- Skip components which do exist -->
                    <continue>
                        <ruleList>
                            <componentTest logic="exists" name="${component_name}"/>
                        </ruleList>
                    </continue>
                    <!-- If it doesn't exist, remove it from the list -->
                    <setInstallerVariableFromRegEx>
                        <name>all_components_list</name>
                        <pattern>(.*)(\s?${component_name}\s.*\(${component_name}\)\s)(.*)</pattern>
                        <substitution>\1\3</substitution>
                        <text>${all_components_list}</text>
                    </setInstallerVariableFromRegEx>
                </actionList>
            </foreach>
            <logMessage>
                <text>getComponentLists: all_components_list = ${all_components_list}</text>
                <ruleList>
                    <compareValues logic="greater" value1="${project.debugLevel}" value2="0"/>
                </ruleList>
            </logMessage>
            <!-- Create comma separated list for all deselection/selection -->
            <setInstallerVariableFromRegEx>
                <name>select_all_components_list</name>
                <pattern>\sproject.[a-z_\(\).]*\s?</pattern>
                <substitution> </substitution>
                <text>${all_components_list}</text>
            </setInstallerVariableFromRegEx>
            <!-- Replace whitespace with comma -->
            <setInstallerVariableFromRegEx>
                <name>select_all_components_list</name>
                <pattern>\s+</pattern>
                <substitution>,</substitution>
                <text>${select_all_components_list}</text>
            </setInstallerVariableFromRegEx>
            <!-- Remove trailing comma -->
            <setInstallerVariableFromRegEx>
                <name>select_all_components_list</name>
                <pattern>,$</pattern>
                <substitution></substitution>
                <text>${select_all_components_list}</text>
            </setInstallerVariableFromRegEx>
            <logMessage>
                <text>getComponentLists: select_all_components_list = ${select_all_components_list}</text>
                <ruleList>
                    <compareValues logic="greater" value1="${project.debugLevel}" value2="0"/>
                </ruleList>
            </logMessage>
            <!-- export variables to global scope i.e. return values -->
            <globalVariables>
                <names>all_components_list select_all_components_list</names>
            </globalVariables>
        </actionList>
    </actionDefinition>

Some notes:

  1. The first list has a tuple of component_name and component_accessor, as any particular component may be contained in a componentGroup in the event that you want to access it's properties. Not sure if this is still necessary, of if Bitrock has an easier way to do that now.
  2. You have to check for the existence of the components (unless you always include them all). This is due to attempting to access a non-existent component's attribute, such as "${component(linux_only).selected}" on windows, throws a runtime error.
  3. The second list can be used to selectAll/deselectAll or selecting/deselecting some other groups, without any errors from missing components.
link

answered 29 May '13, 04:35

DevHopeful_2012's gravatar image

DevHopeful_2012
176131521
accept rate: 9%

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×49
×13
×5

Asked: 23 May '13, 06:42

Seen: 2,101 times

Last updated: 29 May '13, 04:35