Add/remove Directory to a specific env variable ?

Answered

Comments

3 comments

  • Avatar
    wojciechka

    It is not possible to use the built-in actions directly. However, you can use the function below to achieve the same task.

    You can put it inside <project> tag and then simply use it as follows:

    <removeValueFromPathlist>
      <data>${env(MY_APP_PATH)}</data>
      <resultVariable>newpath</resultVariable>
      <value>C:\TOTO</value> 
    </removeValueFromPathlist>
    <addEnvironmentVariable>
      <name>MY_APP_PATH</name>
      <value>${newpath}</value>
    </addEnvironmentVariable>
    

    This will remove the path, properly handling per-platform differences (i.e. ; and : separators appropriately) and cases where the value is first, in the middle, last or only element in the variable.

    The function definition is as follows:

    <project>
    <functionDefinitionList>
        <actionDefinition name="removeValueFromPathlist">
            <actionList>
                <setInstallerVariable name="separator" value=":"/>
                <setInstallerVariable name="separator" value=";">
                    <ruleList>
                        <platformTest type="windows"/>
                    </ruleList>
                </setInstallerVariable>
                <setInstallerVariableFromRegEx name="value" pattern="\" substitution="\\" text="${value}"/>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}${separator}" substitution="${separator}" text="${data}">
                    <ruleList>
                        <regExMatch pattern="${separator}${value}${separator}" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="^${value}${separator}" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="^${value}${separator}" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}$" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="${separator}${value}$" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="^${value}$" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="^${value}$" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <globalVariables names="${resultVariable}"/>
                <setInstallerVariable name="${resultVariable}" value="${data}"/>
            </actionList>
            <parameterList>
                <stringParameter name="data" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="value" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="resultVariable" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
            </parameterList>
        </actionDefinition>
    </functionDefinitionList>
    <!-- ... -->
    </project>
    

    EDIT: A more compact alternative would be (thanks to stasm!):

    <functionDefinitionList>
        <actionDefinition name="removeValueFromPathlist">
            <actionList>
                <setInstallerVariable name="separator" value=":"/>
                <setInstallerVariable name="separator" value=";">
                    <ruleList>
                        <platformTest type="windows"/>
                    </ruleList>
                </setInstallerVariable>
                <setInstallerVariableFromRegEx name="value" pattern="([\\.{}()[\]*?+^$|-])" substitution="\\\1" text="${value}"/>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}${separator}" substitution="${separator}" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="^${value}${separator}" substitution="" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}$" substitution="" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="^${value}$" substitution="" text="${data}" />
                <globalVariables names="${resultVariable}"/>
                <setInstallerVariable name="${resultVariable}" value="${data}"/>
            </actionList>
            <parameterList>
                <stringParameter name="data" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="value" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="resultVariable" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
            </parameterList>
        </actionDefinition>
    </functionDefinitionList>
    
  • Avatar
    DevHopeful_2012

    Since I found this code extremely useful, I thought I would share the one bug that I found in it and the fix. The problem is if the path to remove contains parentheses, such as Program File (x86) in Windows. The code above fails on the first regex pattern and exits the actionList, leaving the path behind.

    To handle this special case, the following additional actions can be performed, which fixes the failure of "value" in the regex pattern:

    <setInstallerVariableFromRegEx name="value" pattern="\(" substitution="\(" text="${value}"/>
    <setInstallerVariableFromRegEx name="value" pattern="\)" substitution="\)" text="${value}"/>
    

    So, the entire code could look something like this:

    <project>
    <functionDefinitionList>
        <actionDefinition name="removeValueFromPathlist">
            <actionList>
                <setInstallerVariable name="separator" value=":"/>
                <setInstallerVariable name="separator" value=";">
                    <ruleList>
                        <platformTest type="windows"/>
                    </ruleList>
                </setInstallerVariable>
                <setInstallerVariableFromRegEx name="value" pattern="\\" substitution="\\\\" text="${value}"/>
                <setInstallerVariableFromRegEx name="value" pattern="\(" substitution="\(" text="${value}"/>
                <setInstallerVariableFromRegEx name="value" pattern="\)" substitution="\)" text="${value}"/>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}${separator}" substitution="${separator}" text="${data}">
                    <ruleList>
                        <regExMatch pattern="${separator}${value}${separator}" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="^${value}${separator}" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="^${value}${separator}" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}$" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="${separator}${value}$" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <setInstallerVariableFromRegEx name="data" pattern="^${value}$" substitution="" text="${data}">
                    <ruleList>
                        <regExMatch pattern="^${value}$" text="${data}">
                            <logic>matches</logic>
                        </regExMatch>
                    </ruleList>
                </setInstallerVariableFromRegEx>
                <globalVariables names="${resultVariable}"/>
                <setInstallerVariable name="${resultVariable}" value="${data}"/>
            </actionList>
            <parameterList>
                <stringParameter name="data" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="value" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="resultVariable" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
            </parameterList>
        </actionDefinition>
    </functionDefinitionList>
    <!-- ... -->
    </project>
    
  • Avatar
    stasm

    It seems the code of removeValueFromPathlist can be improved and simplified.

    First, escaping all regex special symbols in one action:

    <setInstallerVariableFromRegEx name="value" pattern="([\\.{}()[\]*?+^$|-])" substitution="\\\1" text="${value}"/>
    

    Second, <ruleList> restrictions for <setInstallerVariableFromRegEx> are unnecessary in this case and can be removed.

    So entire function is defined as follows:

    <functionDefinitionList>
        <actionDefinition name="removeValueFromPathlist">
            <actionList>
                <setInstallerVariable name="separator" value=":"/>
                <setInstallerVariable name="separator" value=";">
                    <ruleList>
                        <platformTest type="windows"/>
                    </ruleList>
                </setInstallerVariable>
                <setInstallerVariableFromRegEx name="value" pattern="([\\.{}()[\]*?+^$|-])" substitution="\\\1" text="${value}"/>
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}${separator}" substitution="${separator}" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="^${value}${separator}" substitution="" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="${separator}${value}$" substitution="" text="${data}" />
                <setInstallerVariableFromRegEx name="data" pattern="^${value}$" substitution="" text="${data}" />
                <globalVariables names="${resultVariable}"/>
                <setInstallerVariable name="${resultVariable}" value="${data}"/>
            </actionList>
            <parameterList>
                <stringParameter name="data" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="value" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
                <stringParameter name="resultVariable" description="" explanation="" value="" default="" allowEmptyValue="0" width="0"/>
            </parameterList>
        </actionDefinition>
    </functionDefinitionList>
    

Please sign in to leave a comment.