The knowledge base is no longer actively updated, we have moved all content to our Community Support Forum

How to create serial key pages

Author: BitRock Support       Date: September 14, 2009 14:27       Tags: User input and custom installer pages

There are several ways of creating a serial key page using InstallBuilder. You can use an string parameter:

  • - Using an <stringParameter>: This has the advantage of letting your users to comfortably copy and paste the code but you will need to be more permissive with the format

  •         <stringParameter>
                <name>licensekey</name>
                <title>License key</title>
                <explanation>Please introduce your license key:</explanation>
                <description>Key:</description>
                <allowEmptyValue>0</allowEmptyValue>
                <width>30</width>
                <validationActionList>
                    <throwError>
                        <text>Incorrect format</text>
                        <ruleList>
                            <regExMatch logic="does_not_match" >
                                <pattern>^([0-9]{4})-?([0-9]{4})-?([0-9]{4})-?([0-9]{4})$</pattern>
                                <text>${licensekey}</text>
                            </regExMatch>
                        </ruleList>
                    </throwError>
                </validationActionList>
                <postShowPageActionList>
                    <setInstallerVariableFromRegEx text="${licensekey}" substitution="\1-\2-\3-\4" name="normalizedkey" pattern="^([0-9]{4})-?([0-9]{4})-?([0-9]{4})-?([0-9]{4})$"/>
                </postShowPageActionList>
            </stringParameter>
    



    The snippet above will accept both 1723-4456-7285-4116 and 123456785416 as valid formats and will store "1723445672854116" internally in "normalizedkey"

  • - Using multiple <stringParameter> in a <parameterGroup>: Using this approach will generate a more elaborate page layout, forcing the user to respect the "XXXX-XXXX-XXXX-XXXX" format
            <parameterGroup>
                <name>licensekey</name>
                <title>License Key</title>
                <explanation>Please enter your registration key</explanation>
                <value></value>
                <default></default>
                <orientation>horizontal</orientation>
                <parameterList>
                    <!-- A stringParameter for each field. We include a "-" as description to simulate the license-type format -->
                    <stringParameter name="code1" description="" allowEmptyValue="0" width="4"/>
                    <stringParameter name="code2" description="-" allowEmptyValue="0" width="4"/>
                    <stringParameter name="code3" description="-" allowEmptyValue="0" width="4"/>
                    <stringParameter name="code4" description="-" allowEmptyValue="0" width="4"/>
                </parameterList>
                <validationActionList>
                    <foreach variables="field">
                        <values>"${code1}" "${code2}" "${code3}" "${code4}"</values>
                        <actionList>
                            <throwError>
                                <text>${field}: Field should be four digits length</text>
                                <ruleList>
                                    <compareTextLength text="${field}" logic="equals" length="4" negate="1"/>
                                </ruleList>
                            </throwError>
                            <throwError>
                                <text>${field}: Should be a pure digit string</text>
                                <ruleList>
                                    <stringTest text="${field}" type="digit" negate="1"/>
                                </ruleList>
                            </throwError>
                        </actionList>
                    </foreach>
                </validationActionList>
                <postShowPageActionList>
                    <setInstallerVariable name="${normalizedkey}" value="${code1}${code2}${code3}${code4}"/>
                </postShowPageActionList>
            </parameterGroup>
    



  • - Multiple user interfaces: The disadvantage of using this complex layout is that it is not correctly displayed in text mode. To solve it, you can include both solutions and select them base on the installation mode:

        <stringParameter>
            <name>licensekeytext</name>
            <title>License Key</title>
            <description>Please introduce your registration key:</description>
            <ruleList>
                <compareText text="${installer_ui}" logic="equals" value="text"/>
            </ruleList>
        </stringParameter>
    
        <parameterGroup>
            <name>licensekay</name>
            <title>License Key</title>
            <explanation>Please enter your registration key</explanation>
            <value></value>
            <default></default>
            <orientation>horizontal</orientation>
            <parameterList>
                ...
            </parameterList>
            <ruleList>
                <compareText text="${installer_ui}" logic="equals" value="gui"/>
            </ruleList>
        </parameterGroup>
    




Once we have the key from the user, we have to validate it. The validation could be as simple as just comparing it with a harcoded list of licenses in the XML (or provided at built time) or passing it to an external validator program.

The first case will be as simple as using a action with a rule:

 <parameterGroup>
   <name>licensekey</name>
     ...
     <validationActionList>    
        ...    
        <postShowPageActionList>
           <setInstallerVariable name="${normalizedkey}" value="${code1}${code2}${code3}${code4}"/>
        </postShowPageActionList>                                                                                                                                                                                                         
        <throwError>                                                                                                                                                                                                                       
           <text>The provided license key is not correct</text>                                                                                                                                                                     
           <ruleList>                                                                                                                                                                                                                     
             <compareText>                                                                                                                                                                                                              
               <logic>does_not_contain</logic>                                                                                                                                                                                  
               <text>'1043610610014115484','790910610318458616','102977671916110224','2070626417075211'</text>                                                                                                                  
               <value>'${normalizedkey}'</value>                                                                                                                                                                               
             </compareText>                                                                                                                                                                                                             
           </ruleList>                                                                                                                                                                                                                    
        </throwError>                                                                                                                                                                                                                      
     </validationActionList>
     ...
 </parameterGroup>



Using a custom external validation is still really easy to implement though. First of all we need to include in our bundled files the validator:


<componentList>                                                                                                                                                                                                                        
  <component>                                                                                                                                                                                                                          
     <name>registration</name>                                                                                                                                                                                                   
     <folderList>                                                                                                                                                                                                                      
         <folder>                                                                                                                                                                                                                      
            <name>registrationWindows</name>                                                                                                                                                                                     
            <platforms>windows</platforms>                                                                                                                                                                                       
            ...                                                                                                                                                                                                                              
            <distributionFileList>                                                                                                                                                                                                     
              <distributionFile>                                                                                                                                                                                                       
                <origin>path/to/validatekey.exe</origin>                                                                                                                                                                         
              </distributionFile>                                                                                                                                                                                                      
            </distributionFileList>                                                                                                                                                                                                    
            <ruleList>                                                                                                                                                                                                                 
              <isTrue>                                                                                                                                                                                                                 
                <value>0</value>                                                                                                                                                                                                 
              </isTrue>                                                                                                                                                                                                                
             </ruleList>                                                                                                                                                                                                               
         </folder>                                                                                                                                                                                                                     
     </folderList>                                                                                                                                                                                                                     
  </component>                                                                                                                                                                                                                         
</componentList>



The attached <isTrue> rule is just used to avoid the validator program from being extracted automatically in the unpack process. As we need to validate the key before the installation step, we have to manually unpack it:

<parameterGroup>
  <name>licensekey</name>
  ...                                                                                                                                                                                                                                        
  <validationActionList>                                                                                                                                                                                                               
    ...                                                                                                                                                                                                                                      
    <unpackFile>                                                                                                                                                                                                                       
       <component>registration</component>                                                                                                                                                                                       
       <destination>${system_temp_directory}/validatekey.exe</destination>                                                                                                                                                       
       <folder>registrationWindows</folder>                                                                                                                                                                                      
       <origin>validatekey.exe</origin>                                                                                                                                                                                          
    </unpackFile>                                                                                                                                                                                                                      
    <runProgram>                                                                                                                                                                                                                       
       <program>${system_temp_directory}/validatekey.exe</program>                                                                                                                                                               
       <programArguments>${normalizedkey}</programArguments>                                                                                                                                                                  
       <customErrorMessage>The provided license is not correct</customErrorMessage>                                                                                                                                              
    </runProgram>                                                                                                                                                                                                                      
  </validationActionList>
     ...
  <postShowPageActionList>
     <deleteFile path="${system_temp_directory}/validatekey.exe"/>
  </postShowPageActionList>
 </parameterGroup>



The code above takes care of unpacking the validator program and calling it with the provided license number. If the validator program returns an error, it means that the code is not valid and an error will be thrown. The text displayed in case of error is controlled with the <customErrorMessage> tag in the <runProgram> action. As the error is occurring in the </validationActionList>, the installation won't abort, it will just redraw the same page. We also take care of deleting the validator from its temporary location.


If you require more control aver the return code, you can also catch the execution of the <runProgram> and then check the return code:

<parameterGroup>
  <name>licensekey</name>
  ...
  <validationActionList>                                                                                                                                                                                                               
    ...                                                                                                                                                                                                                                      
    <runProgram>                                                                                                                                                                                                                       
       <abortOnError>0</abortOnError>                                                                                                                                                                                            
       <program>${system_temp_directory}/validatekey.exe</program>                                                                                                                                                               
       <programArguments>${registrationcode}</programArguments>                                                                                                                                                                  
       <showMessageOnError>0</showMessageOnError>                                                                                                                                                                                
    </runProgram>                                                                                                                                                                                                                      
    <deleteFile>                                                                                                                                                                                                                       
       <path>${system_temp_directory}/validatekey.exe</path>                                                                                                                                                                     
    </deleteFile>                                                                                                                                                                                                                      
    <throwError>                                                                                                                                                                                                                       
       <text>The provided license is invalid</text>                                                                                                                                                                              
       <ruleList>                                                                                                                                                                                                                      
         <compareValues>                                                                                                                                                                                                               
           <logic>equals</logic>                                                                                                                                                                                                 
           <value1>${program_exit_code}</value1>                                                                                                                                                                                 
           <value2>1</value2>                                                                                                                                                                                                    
         </compareValues>                                                                                                                                                                                                              
       </ruleList>                                                                                                                                                                                                                     
    </throwError>                                                                                                                                                                                                                      
    <throwError>                                                                                                                                                                                                                       
       <text>The provided license is expired</text>                                                                                                                                                                              
       <ruleList>                                                                                                                                                                                                                      
         <compareValues>                                                                                                                                                                                                               
           <logic>equals</logic>                                                                                                                                                                                                 
           <value1>${program_exit_code}</value1>                                                                                                                                                                                 
           <value2>2</value2>                                                                                                                                                                                                    
         </compareValues>                                                                                                                                                                                                              
       </ruleList>                                                                                                                                                                                                                     
    </throwError>                                                                                                                                                                                                                      
    <throwError>                                                                                                                                                                                                                       
       <text>Unknown error validating the license</text>                                                                                                                                                                         
       <ruleList>                                                                                                                                                                                                                      
         <compareValues>                                                                                                                                                                                                               
           <logic>deoes_not_equal</logic>                                                                                                                                                                                        
           <value1>${program_exit_code}</value1>                                                                                                                                                                                 
           <value2>0</value2>                                                                                                                                                                                                    
         </compareValues>                                                                                                                                                                                                              
       </ruleList>                                                                                                                                                                                                                     
    </throwError>                                                                                                                                                                                                                      
  </validationActionList>  
 </parameterGroup>



It first check the expected error exit codes (1,2) and also includes a fall back error in case the license was not correctly validated (${program_exit_code} > 0) but the return code was not considered.