More installation options with install4j

2010-12-21
Posted by Emmanuel


Last week, I explained how to build an installer with install4j for Sweet Home 3D, that would behave as the one distributed on the web site of the program.

But Sweet Home 3D and install4j provide some options that could be nice to offer to end users at installation time like:



  • keeping the language chosen at installation as the default language of the program,
  • configuring the max memory amount used by the program from the RAM available in the computer,
  • offering to download and install an optional program like the Furniture Library Editor,
  • downloading some optional files like archives containing 3D models,
  • offering special options when the program is installed on a USB key,
  • offering to delete program and configuration files during uninstallation,
  • translating the text of the special options added to the installer,
  • installing the program in unattended mode to speed up its deployment in
    schools.


Storing the chosen language

In Sweet Home 3D, the user may change the language used in the graphic interface with the preferences panel displayed when he selects the File > Preferences menu item. The persistence of his choice is managed with Java Preferences class which stores its values in the registry under Windows. install4j offers an action able to set the value of a Java preference and I'm going to use it to store the language used in the installer.

As I want this action to occur after files were installed, I select Installation node in install4j and choose Add Action in its contextual menu.
Blog figure

I type the the first letters of "preferences " in the Filter text field and select the Set a key in the Java preference store action among the 5 actions dealing with preferences.
Blog figure

Once I click on OK, I fill the Java preference properties of the action from the matching value read in Sweet Home 3D. I set Package name value to "com.eteks.sweethome3d.io " and Key value to "language ".
The value of the Value text field must be set according to the language currently used in the installer, something stored in one of the install4j variables. To find it out, I click on the button arrow at the right of the text field and select the Insert Installer Runtime Variable option.
Blog figure

In the Select Installer Runtime Variable dialog box, I filter variables with the first letters of "language " and choose sys.languageId variable.
Blog figure

Finally, I choose User specific for Preference root field.
Blog figure

Configuring the max memory of the program

Sweet Home 3D may require a lot of memory in some circumstances, and the default amount of maximum memory used by a Java Virtual Machine is generally not enough to let the program work correctly for big layouts. At the opposite, if too much memory is required, the program may slow down too much because the operating system will have to manage the missing RAM with disk swapping. A nice option could be to fix the maximum memory used by the JVM by program according to the available physical memory. This amount of memory is passed to the JVM with the option -Xmaaaam where aaaa matches the maximum memory in MB.

I already set -Xmx to 512m during the configuration of a launcher by setting the VM parameters value at the fourth step of the launcher creation wizard.
Blog figure

To set this value according to the memory available on the end user computer, the easiest way is to remove the -Xmx512m option from VM parameters and add an action to update VM parameters when the installer is run. As this action should happen at the end of the installation, I select the Installation node, click on the Insert button (the button with a green plus) and select the Add Action menu item.
Blog figure

In the Select an Installation Action dialog box, I choose the Add VM Options action,
Blog figure

and once I click on OK, I edit the properties of the action to set SweetHome3D as Launcher value and enter the text "${installer:xmx} " in VM options text field.
Blog figure

This value references the installer:xmx variable that will be evaluated at installation time, when the installer will be run. As I need to create this variable and give it a value, I click again on the Insert button and select Add Action menu item. This time, I choose the Set a variable action in the Select an Installation Action dialog box.
Blog figure

Once I click on OK, I move the new action one row up before the Add VM options action by clicking on the blue up arrow, edit the properties of the action to set the "xmx " name of the new variable without its installer prefix, and click on the button with an ellipsis at the right of the Script text field to edit its value.
Blog figure

This opens a text editor where I have to enter a Java expression whose value will be saved to the xmx variable.
Blog figure

The comment displayed by the editor suggests I can use the two context and action parameters if required, and the classes of these two parameters are com.install4j.api.context.InstallerContext and com.install4j.api.actions.InstallAction shown as hyperlinks to their respective javadoc pages.
Blog figure

The great thing is that editor offers auto completion when I press Ctrl + space keys! For example, if I try to complete "co " I'll get "context " at the top of the suggested items and other items starting by "co ".
Blog figure

I choose context, type a dot to invoke a method of the InstallerContext class, but there are so many choices that it's quite difficult to find out the method that returns the memory available in the computer where the installer runs (this value isn't available in Java SE 6 too).
Blog figure

Therefore I explore the help file, which seems pretty complete, since I find the information I need with a search of the "memory " keyword which brings me to the method getPhysicalMemory in the com.install4j.api.SystemInfo class.
Blog figure

As this method is static, I finally enter the expression
"-Xmx" + (SystemInfo.getPhysicalMemory() / 2 / 1024 / 1024) + "m"
and as the green square drawn at the end of line confirms, the syntax of my expression is correct,
Blog figure

I click on OK, save my install4j project, build it and run the installer to check how it works.

As setting this option won't change anything at the screen, I run SweetHome3D.exe executable file in a command window with the option /create-i4j-log that will create a temporary log file. To help me to find this log file, install4j displays an information dialog box recalling where it can be found.
Blog figure

Reading this file I can see a vmoption line with -Xmx755m option stating the half of the 1.5 GB memory of my computer might be occupied by the Java program.

Downloading an optional program

A program called the Furniture Library Editor was recently added as a separate application. It allows the user to import and edit faster the attributes of a group of 3D models instead of importing them one by one in the program.

This program is a Jar executable application and I want to suggest it as an option in the installer. As it is around 5 MB large, it won't be bundled with the installer but downloaded if the user wants to install it.

To make it a downloadable file, I have to add it to the installer Files and then select it as a downloadable component in the Media wizard. Therefore, I download FurnitureLibraryEditor-1.2.jar in the Installer directory on my desktop, and add it to the Installation directory node in the Files screen as a single file with the Insert button (the button with a green plus).
Blog figure

Then I create a new launcher for the Furniture Library Editor as I did for Sweet Home 3D, by clicking on the New launcher icon in Launchers screen.
Blog figure

This time, I name the executable file as FurnitureLibraryEditor, select the Allow only a single running instance of the application option,
Blog figure

fill the windows version info resource,
Blog figure

configure its icon in the Icon step,
Blog figure

configure program launch by adding FurnitureLibraryEditor-1.2.jar archive in class path and using com.eteks.furniturelibraryeditor.FurnitureLibraryEditorBootstrap as main class,
Blog figure

and no splash screen. I finally see the new laucher item in install4j.
Blog figure

To make FurnitureLibraryEditor-1.2.jar and its launcher optional files, I then click on the Installation Components tab to create components that group files by application. I click on the Insert button, enter first the name of the basic component that will contain the Sweet Home 3D application files and click on OK.
Blog figure

In the Files tab, I select all the files except FurnitureLibraryEditor-1.2.jar and its launcher,
Blog figure

Then I create a second component for the FurnitureLibraryEditor-1.2.jar file that will be downloaded.
Blog figure

In the Options tab of that component, I unselect Initially selected for installation option and select Downloadable component
Blog figure

As the launcher of the Furniture Library Editor won't be downloaded but will be bundled with the installer (launchers are small files of 250 KB), I create a third installation component named Furniture Library Editor launcher for it, select [Launcher] FurnitureLibraryEditor file and change the options to hide it to the end users, because it would be useless to ask them to check two options if they want to install the Furniture Library Editor.
Blog figure

Now that installation components are created, I go to the Installer screen and select the Installation components node, that will be displayed from now on since I created installation components.
Blog figure

As I need to select the Furniture Library Editor launcher component if the Furniture Library Editor component is selected by the user, I click on the ellipsis button beside Selection change script field and enter the matching Java statement
Blog figure

Each component, screen or action in install4j has a unique ID and I need to find the ID of the Furniture Library Editor launcher component to pass a correct value to getInstallationComponentById method call. The IDs of install4j items can be displayed by clicking on the Show IDs button Blog image found on many screens, but to avoid closing the editor window, I prefer here to click on the Insert ID button to find the desired ID. This will open a dialog box where I enter the first letters of "Furniture " and find the ID of the component is 376.
Blog figure

I click on OK to close the script window, and finally go to the Media screen to update the Windows media file
Blog figure

that requires to be completed with the URL http://ovh.dl.sourceforge.net/project/sweethome3d/FurnitureLibraryEditor/ where FurnitureLibraryEditor-1.2.jar can be downloaded from.
Blog figure

I build a new installer and test it. A new step is now displayed that will let me choose what I want to install.
Blog figure

I select the Furniture Library Editor option and check that the new application is available in Sweet Home 3D group.
Blog figure

Downloading other optional files




Sweet Home 3D lets the user import pieces of furniture one by one, but also by group of pieces from .sh3f files (that the Furniture Library Editor can edit). At this time, four .sh3f files are available to download 400 models separately, but I'm going to offer them as optional files during installation time.

The 4 files to download are these ones:




Once downloaded, these files should be unzipped in a private directory of Sweet Home 3D that depends on the target system. Under Windows 7 and Vista, it should be under the directory C:UsersuserAppDataRoamingeTeksSweet Home 3Dfurniture and under previous versions of Windows C:Documents and SettingsuserApplication DataeTeksSweet Home 3Dfurniture, where user is the user's login name.

This time, unlike during the previous part where I installed an optional program, I'll create an Installation Components associated with no files, then use the Download file and Extract a ZIP file actions.

Thus, I create four additional Installation components in the proper tab of the Files screen. To simplify the way to find them later, I create a custom ID for each of them with a value equal to its name.
Blog figure

Then I unselect the Initially selected for installation option and select the Downloadable component option for the 4 new components.
Blog figure

To manage the download of the optional files, I go to the Installer screen, select the Installation node and insert a Download file action.
Blog figure

In the properties of the Download file action, I set the URL to "http://ovh.dl.sourceforge.net/project/sweethome3d/SweetHome3D-models/3DModels-1.1.1/3DModels-Contributions-1.1.1.zip ", the Target file to "${installer:sys.workingDir}/3DModels-Contributions-1.1.1.zip " and select the Delete downloaded file on exit since it won't be needed once unzipped.
Blog figure

Then I click on the ellipsis button beside the Control Flow / Condition expression field to enter the condition when this action should be executed
Blog figure

To unzip the downloaded file to the right directory, I insert a Extract a ZIP file action after the Download action.
Blog figure

In the properties of the Extract a ZIP file action, I set the Zip file to "${installer:sys.workingDir}/3DModels-Contributions-1.1.1.zip " and enter a File filter script condition that will extract only files ending with .sh3f.
Blog figure

I enter "${installer:privateDir}furniture " in Destination directory field because the place where the application configuration data is stored varies from one operating system to the other, and set the value of the privateDir variable with a new Set a variable action, setting its script to the corresponding
method in Sweet Home 3D.
Blog figure

Finally, I move the Set a variable action two rows up and I create the same Download file / Extract a ZIP file actions for the 3 other optional downloads. Installation screen runs 20 actions now!
Blog figure

Once built, the new version of the installer displays the options to download the optional files,
Blog figure

and if I check some of them, it will download them.
Blog figure

Setting special options

From the previous parts, you understood that like many other applications, Sweet Home 3D stores its configuration data in private directories. But some users want to be able to move an application and its configuration around without bothering how to copy this data, and requested to make Sweet Home 3D portable (not across operating systems, but across different computers). This ended up by the new com.eteks.sweethome3d.preferencesFolder and com.eteks.sweethome3d.applicationFolders system properties that give the directories where Sweet Home 3D will store its configuration data.

To spare end users the difficulty to set these properties, I'm going to add a new screen shown after the Installation location screen where the user will be able to choose whether he wants to install Sweet Home 3D as a portable application or not, when he chose a removable drive as installation destination.

To create this customized screen in install4j, I select the Installation location node in Installer screen, click on the Insert button and choose Add screen option.
Blog figure

In the Select an Installation Screen dialog box, I choose the Configurable form item in the list of screens and check Insert after selection at the bottom of the dialog box.
Blog figure

Once I click on OK, the new screen is added in the Installer screen sequence.
Blog figure

I click first on the Configure Form Components button to add a check box to the empty form. In the dialog box that appears, I click on the Insert button and choose the Add Form Component option.
Blog figure

This will open another dialog box in which I can choose among more than 30 different components. I choose a Check box component,
Blog figure

and click on OK. In the properties list of the inserted check box, I enter "Install as a portable application " as the text check box, enter "portable " as the variable name associated to this check box and select the Initially selected and Request focus check boxes.
Blog figure

As this new option isn't so easy to understand, I click on the ellipsis button of the Help text field and enter a text that explains this option,
Blog figure

and click on OK. Then, I click on the Preview Form button at the top right of the dialog to check how the check box and its help text will be shown.
Blog figure

This looks nice but the screen title and subtitle are still missing! I close the Configure Form Components and click on the Properties tab of the Configurable form node,
where I enter "Removable drive option " in Screen title text field and "Should application installation be portable? " in Screen subtitle text field.
Blog figure

As this screen should be displayed only if the user chose a removable drive, I finally click on the ellipsis button of the Condition expression property to enter the condition.
Blog figure

As this condition can be checked only under Windows I check first if the installer is running under Windows with a call to Util.isWindows(), then I use the getDriveType method of the WinFileSytem class to check if the installation directory chosen by the user is removable or not.

The new screen is now configured, and I have to use the value of the portable variable bound to the check box to configure Sweet Home 3D accordingly on the installation screen. As this variable won't exist if the new screen isn't displayed, I predefine it by clicking on the Installer node, then on the Configure Predefined Installer Variables button in the Installer Variables tab.
Blog figure

In the Edit Installer Runtime Variables For "Installer" dialog box, I click on the Insert button and choose the Add New Predefined Installer Variable option.
Blog figure

I set the name of the new variable as "portable ", set its type to Boolean and its default value to false.
Blog figure

I click on OK and use the portable value in the Installation node to add new VM options that will set the desired system preferences: I select the Set a variable action that defines the privateDir variable to add this new action after it, click on the Insert button, select Add Action option and choose the Add VM options action.
Blog figure

I confirm my choice, select SweetHome3D launcher, enter the two lines
"-Dcom.eteks.sweethome3d.preferencesFolder=${installer:privateDir} " and
"-Dcom.eteks.sweethome3d.applicationFolders=${installer:privateDir} " in its VM options text field, and set its condition expression as "context.getBooleanVariable("portable") "
Blog figure

These options reference the variable privateDir whose value must take into account the value of the portable variable, too. Therefore, I select the Set a variable action that defines the privateDir variable and click on the ellipsis beside its Script field to update it.
Blog figure

While editing this script, I got the context.getVariable("sys.installationDir") Java expression that returns the value of the sys.installationDir install4j variable by clicking on the Insert Variable button, chosing Insert Installer Runtime Variable item and selecting the sys.installationDir variable.
Blog figure

I build this updated configuration and try the new version of the installer that displays the new screen if I choose to install it on a USB key.
Blog figure

Uninstalling a program and its configuration data

Sweet Home 3D stores user preferences and configuration data in private directories to help users to upgrade the installed version of the software without losing data. But sometimes some users want to really remove all information bound to the installed software. Installers built with install4j are highly configurable, and their uninstaller counterpart is as much configurable as the installer, so I'm going to add a screen that will ask the user whether he wants to delete Sweet Home 3D private files or not, and add some actions that will handle his answer.

I select the Uninstaller node in Installer screen, click on the Insert button, select the Add Screen option and choose the Additional confirmations screen.
Blog figure

Once I click on OK, I move the Additional confirmations screen after Uninstall Welcome screen with the blue arrow button, and click on the Configure Form Components buttons.
Blog figure

In this form, I'm going to add a check box to confirm the deletion of Sweet Home 3D private data:

I click on the Insert button, select the Add Form Component option and choose Check box among the list of components.
Blog figure

I enter "Sweet Home 3D private data " as the displayed Text,
Blog figure

and click on the ellipsis beside Help text field to detail what will be deleted.
Blog figure

Finally, I enter "privateData " in the Variable name text field associated with this check box.

I close the Configure Form Components dialog box and click on Unistallation node to add a new action to it.
Blog figure

I filter the actions list with "delete " and choose the Delete a node or key in the Java preference store action.
Blog figure

I enter the "com.eteks.sweethome3d " package in the properties list, unselect the Only if empty check box and let the Key field empty to delete all the preferences associated to this package node.
Blog figure

I click on the ellipsis beside the Condition expression field, insert the value of the privateData variable to check the condition, and confirm my choice.
Blog figure

To delete private files, I add a Delete files and directories action to Unistallation node with the same Condition expression and select the Recursive option.
Blog figure

The files to delete are in the directory referenced by the privateDir variable created at installation time, but I need it also at uninstallation time. Like privateData variable, the value of an installer variable is available in the uninstaller if it's predefined in the installer and marked as a response file variable. A response file is a properties file that contains key-value pairs for installer variables. This file is created during installation process and is reused during uninstallation.

All the variables bound to a form component like the portable variable bound to the Install as a portable application check box, are automatically saved in a response file. But the privateDir variable isn't bound to any component, and I have to define it as a predefined variable and register it as a response file variable.

Thus, I click on the Installer node, select Installer Variables and click on the Configure Predefined Installer Variables button.
Blog figure

I click on the Insert button, select the Add Predefined Installer Variable option and enter the name "privateDir ".
Blog figure

I confirm my choice and add a new Run script action to the Startup node
Blog figure

that will register the privateDir variable as a response file variable.
Blog figure

Finally, I select again the Delete files and directories action, and complete its Files and directories field by clicking on the ellipsis button beside it. In the Edit Files dialog box, I click on the Insert and edit the file name by clicking on the arrow button to select the installer privateDir variable.
Blog figure

Once done, I can build the media files to test the installer and uninstallers.
Blog figure

When I uninstall Sweet Home 3D, I'll get a new screen showing the additional option.
Blog figure

If I check the option, all the configuration data is deleted as expected.


Translating new options

Some texts in the screens and the options added during the two previous steps aren't predefined in install4j, and I'll have to translate them. Handling translation in install4j works similarly to Java with properties text files where each translated text is associated to a key. The differences in install4j are that it's not mandatory to add a language suffix to each translated properties file and these files can be saved in UTF-8 encoding if they use utf8 file extension (until Java 6, Java properties file supported only ISO-8859-1 encoding which forces you to write characters that don't exist in this encoding with uxxxx sequence).

The properties files used by the installer are defined in the Languages tab of the General Settings screen of the installer project, and after clicking on the New button beside Custom localization file field, I choose to name it "InstallerTranslation.utf8 ".
Blog figure

Once I click on the Create button, a text editor is opened to let me define some properties or override existing ones in the installer. I close the editor and prefer to add the properties one by one, by editing the texts to translate where they are defined in the project. In the Installer screen, I select the Configurable form node and in its Properties tab, copy to the clipboard the text of the Screen title field, click on the arrow button beside it and select the Insert I18N Message option (I18N means Internationalization, the 18 number matching the the number of letters between the first and the last letter of this long word).
Blog figure

In the Select I18N Message dialog box, I click on the Edit link to enter a new key/value pair in the InstallerTranslation.utf8 file.
Blog figure

I enter the text "portableScreenTitle=Removable drive option " in the editor,
Blog figure

click on OK, and select the new key that appears in the Custom messages list.
Blog figure

Once done, the text of the Screen title field is replaced by ${i18n:portableScreenTitle}.

I perform the same operation for the other 5 new texts that need to be translated.

The two Help texts are replaced by clicking in the Insert Variable button shown in their editor and choosing the Insert I18N Message option.
Blog figure

Once done with the InstallerTranslation.utf8 file, i just have to translate this file in each supported language and add them on the Languages tab of the General Settings screen. For example, I can translate the texts to French in a file InstallerTranslationFrench.utf8 and add it to project.
Blog figure

Installing a program in console or unattended mode

Installing a program with a graphic user interface is nice for most users, but many environments offer only a command line interface. install4j offers such a mode without any additional change to the installer:
instead of answering questions with buttons, text fields and check boxes, the end user just uses the keyboard to answer. The console mode is used when the argument -c is passed to the installer program. Under Windows XP / Vista / 7, Sweet Home 3D installer can be run with the following command:
start /wait SweetHome3D-3.0-windows.exe -c

which will give the following results.
Blog figure

install4j offers also an unattended mode, something that may be very handy when you have to install a program the same way on different computers. In that mode launched with a -q argument passed to the installer program, the installation runs by itself until the end without asking any questions. The directory where the program should be installed can be specified with the -dir argument and the answers to the installer questions that should be different from their default values can be specified in a response file by passing the -varfile argument.

The easiest way to generate such a response file is to run the program in another mode and retrieve the response.varfile file created by the installer in the .install4j subdirectory of the directory where program was installed. This file is a text file that contains installer variables and their values that may be edited with any text editor if needed. Under Windows XP / Vista / 7, Sweet Home 3D can be installed in unattended mode with the following command:
start /wait SweetHome3D-3.0-windows.exe -q -varfile response.varfile

Conclusion

install4j lets you customize your installer in many ways. You can configure it to install some optional items and perform some special operations. You can also use your Java skills to program customized conditions or any required piece of code, in an editor that supplies the great features of modern IDEs.
Connect
Read with RSS
Subscribe by email
Follow on or
Blog Archive