- 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.
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.
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.
In the
Select Installer Runtime Variable dialog box, I filter variables with the first letters of "
language
" and choose
sys.languageId variable.
Finally, I choose
User specific for
Preference root field.
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.
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.
In the
Select an Installation Action dialog box, I choose the
Add VM Options action,
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.
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.
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.
This opens a text editor where I have to enter a Java expression whose value will be saved to the
xmx variable.
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.
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
".
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).
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.
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,
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.
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).
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.
This time, I name the executable file as
FurnitureLibraryEditor, select the
Allow only a single running instance of the application option,
fill the windows version info resource,
configure its
icon in
the
Icon step,
configure program launch by adding
FurnitureLibraryEditor-1.2.jar archive in class path and using
com.eteks.furniturelibraryeditor.FurnitureLibraryEditorBootstrap
as main class,
and no splash screen. I finally see the new laucher item in install4j.
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.
In the
Files tab, I select all the files except
FurnitureLibraryEditor-1.2.jar and its launcher,
Then I create a second component for the
FurnitureLibraryEditor-1.2.jar file that will be downloaded.
In the
Options tab of that component, I unselect
Initially selected for installation option and select
Downloadable component
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.
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.
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
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

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.
I click on OK to close the script window, and finally go to the
Media screen to update the
Windows media file
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.
I build a new installer and test it. A new step is now displayed that will let me choose what I want to install.
I select the Furniture Library Editor option and check that the new application is available in
Sweet Home 3D group.
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:\Users\user\AppData\Roaming\eTeks\Sweet Home 3D\furniture and under previous versions of Windows
C:\Documents and Settings\user\Application Data\eTeks\Sweet Home 3D\furniture, 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.
Then I unselect the
Initially selected for installation option and select the
Downloadable component option for the 4 new components.
To manage the download of the optional files, I go to the
Installer screen, select the
Installation node and insert a
Download file action.
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.
Then I click on the ellipsis button beside the
Control Flow / Condition expression field to enter the condition when this action should be executed
To unzip the downloaded file to the right directory, I insert a
Extract a ZIP file action after the
Download action.
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.
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.
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!
Once built, the new version of the installer displays the options to download the optional files,
and if I check some of them, it will download them.
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.
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.
Once I click on OK, the new screen is added in the
Installer screen sequence.
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.
This will open another dialog box in which I can choose among more than 30 different components. I choose a
Check box component,
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.
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,
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.
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.
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.
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.
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.
I set the name of the new variable as "
portable
", set its type to
Boolean and its default value to
false.
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.
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")
"
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.
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.
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.
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.
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.
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.
I enter "
Sweet Home 3D private data
" as the displayed Text,
and click on the ellipsis beside
Help text field to detail what will be deleted.
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.
I filter the actions list with "
delete
" and choose the
Delete a node or key in the Java preference store action.
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.
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.
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.
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.
I click on the
Insert button, select the
Add Predefined Installer Variable option and enter the name "
privateDir
".
I confirm my choice and add a new
Run script action to the
Startup node
that will register the
privateDir variable as a response file variable.
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.
Once done, I can build the media files to test the installer and uninstallers.
When I uninstall Sweet Home 3D, I'll get a new screen showing the additional option.
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
".
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).
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.
I enter the text "
portableScreenTitle=Removable drive option
" in the editor,
click on OK, and select the new key that appears in the
Custom messages list.
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.
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.
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.
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.