Knowledge Base

APPLICABILITY

This article only applies to Excelsior JET for Windows.

SUMMARY

This document explains how to reduce your Java application to a single EXE file after you have natively compiled it with Excelsior JET. A step-by-step guide utilizing free third-party tools is provided.

Disclaimer: This article references third-party software products, namely 7-Zip and ResEdit. These specific products are only used here for illustrative purposes and are not endorsed by Excelsior in any way. Excelsior has no control over the third parties providing those software products and therefore may not be held responsible for their availability and quality. Your use of those products, or any other third party products providing similar functionality will be subject to the terms and conditions of the respective license agreements and other applicable legal instruments.

INTRODUCTION

Even though Excelsior JET compiles your jars and class files into a binary executable, that executable still requires a number of runtime files (JetPackII places them into the $(Root)/rt folder by default.) You must distribute those files alongside the executable. If you do not want to create an installer, you have to export your application as a self-contained directory, and then copy that directory in its entirety.

A workaround exists for those who absolutely must distribute their applications as single executables: use third-party tools to package the exported application as a self-extracting archive that would unpack its contents into a temporary directory, run the application from that directory, wait for its termination, and clean up after itself.

The tradeoff: The startup time of a natively compiled Java app is I/O bound, so the penalty imposed by this workaround may be substantial, especially on warm starts. At the same time, cold start from a slow-seek device such as an optical disk drive will actually be much faster. You will also be unable to fully enjoy the application download size reduction capabilities of Excelsior JET.

The rest of the article explains how to implement the above workaround using the excellent free 7-Zip archiver by Igor Pavlov, and how to “personalize” the resulting executable with ResEdit. You may of course use tools of your choice instead.

DETAILS

To reduce your natively compiled Java application into a single executable using 7-Zip, do the following:

  1. If you do not have 7-Zip installed, download it from 7-zip.org and install it. We tested the stable 4.65 release.
  2. Download the extras package (7z_extra) from 7-zip.org. It includes so called “SFXs for installers”, which you will need.
  3. Use JetPackII to export your application as a self-contained directory.
  4. Use 7-Zip to package the contents of that directory into a .7z archive. e.g. MyApp.7z.
  5. Create a configuration file for the SFX module. It is a plain text file that starts and ends with special marker lines. Make sure to save it in UTF-8 encoding if non-ASCII characters are present in pathnames or messages. For details, refer to the description of the -sfx command line switch in 7-Zip Help.

    For instance, if your compiled application that you want to launch is called MyApp.exe, the configuration file may have name MyApp.cfg and look like this:

    ;!@Install@!UTF-8!
    Progress="No"
    RunProgram="MyApp.exe"
    ;!@InstallEnd@!

    The line “Progress="No"” is optional. It suppresses the extraction progress dialog.

  6. Concatenate the SFX module, the configuration file, and the .7z file containing your exported application (in this order):

    copy /b 7zS.sfx + MyApp.cfg + MyApp.7z MyApp-standalone.exe

    Notice the use of the /b switch to force binary concatenation!

Now, if you run MyApp-standalone.exe on another system, the SFX module will silently extract MyApp.7z into a temporary directory, run MyApp.exe from that directory, wait for its termination and remove the temporary directory and all its contents.

Note: A UAC prompt may display upon application startup on Windows Vista and Windows 7:

Unwanted UAC Prompt
Unwanted UAC Prompt

(As you may see, signing the executable does not help).

To learn what causes this problem and how to solve it, refer to the “Getting Rid of UAC Prompt” in the ADVANCED section below.

ADVANCED

Getting Rid of UAC Prompt

Starting from Windows Vista, a program author may indicate the required privilege level to the operating system by embedding an application manifest within the program. However, the original 7-Zip SFX modules do not have manifests at all, thus triggering a UAC prompt upon launch.

Fortunately, it is very easy to fix this — just add a manifest requesting asInvoker execution level to the SFX module. Refer to the next section for an easy way to do that.

Customizing the SFX Module

Whatever your application is, the icon and version information of the SFX module will display in Windows Explorer and elsewhere /The admin shield on the icon is an indicator of the above UAC prompt issue/ :

image image

You will likely wish to replace these with icon and data specific to the packaged application. To avoid rebuilding the SFX module from source, use a resource editor that can edit binary resources in-place. The below instructions assume usage of a freeware resource editor called ResEdit.

To begin:

  1. Copy 7zS.sfx to, say, MyApp-sfx.exe (ResEdit has no idea about the “.sfx” extension, and won’t open the SFX module file unless you change its extension to “.exe”.)
  2. Start ResEdit, cancel the include path setup dialog, and open MyApp-sfx.exe as a project.

To add an application manifest:

  1. Select Add Resource / Manifest from the File menu. ResEdit shall display a dialog box asking if you want it to generate a manifest.xml file for you.
  2. Click Yes.

The default manifest should eliminate the UAC prompt just fine. If you want to double-check, make sure that it includes the following:

<security>
  <requestedPrivileges>
    <requestedExecutionLevel
      level="asInvoker"
      uiAccess="false"/>
  </requestedPrivileges>
</security>

To replace the SFX icon with your application icon:

  1. Select Add Resource / Icon from the File menu.
  2. Select Create from an existing file and click Next.
  3. Select the desired icon file and click Open.
  4. Now right-click the original SFX icon node in the Resources pane and select Remove from Project.

To edit version information:

  1. Expand “Version Information” and double-click the only node under it.
  2. Now edit version numbers, product and company names as you see fit. You may also add version information blocks in other languages/encodings.

Save the project and exit ResEdit. MyApp-sfx.exe is now “personalized” with your app’s icon and version information. Just make sure to change your build scripts to use the customized SFX module instead of the original 7zS.sfx.

Here is the result:

image image

Notice that there is no more admin shield on the icon, thanks to embedding the application manifest into the SFX module. Now the application will start without a UAC prompt.

For some reason, our copy of ResEdit does not save changes to File Version and Product Version fields in the General Information section, As you may see, they stayed at 4.65.0.0. If this is important to you, you may wish to try some other resource editor.

Avoiding PCA Warnings

Under certain circumstances, e.g. if the packaged application was run from a CD, Windows Program Compatiblity Assitant (PCA) may come into play upon application termination, claiming that it might not have been installed correctly. Basically, PCA wrongfully detects the packaged app as a setup, and raises an alert after it leaves no trace in Add/Remove Programs.

The precense of an UAC manifest disables PCA on Windows Vista, but not on Windows 7. Windows 7 added support for the <compatibility> section in application manifests (Windows Server 2008 R2 is also supposed to recognize it.) If you add the following section to the SFX module manifest, the PCA warning shall not appear:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
  <application>
    <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
    <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
    <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
  </application>
</compatibility>

Note: As of version 1.5.4, you may not edit the manifest file in ResEdit. Suggested workaround:

  1. Add the default manifest as desribed above.
  2. Select the entire content of the manifest, copy it to clipboard and paste into a plain text editor of your choice.
  3. Add the <compatibility> section from above.
  4. Save the extended manifest as a plain text file, e.g. manifest.xml.
  5. Right-click the manifest node in ResEdit and select Remove from project from the pop-up menu.
  6. Select Add Resource / Manifest from the File menu.
  7. In the dialog box, click No. A file dialog shall open. Select the manifest.xml file you previously saved.
  8. Save the project and exit ResEdit.

Portable Applications

If you are making a portable application, as in “designed to run on any computer from a USB stick”, it may need to know where the original self-extracting executable resides, as any files it would have stored into the temporary directory will be removed upon its termination.

You may not supply this information with the self-extraction module that comes with 7-Zip. Fortunately, Oleg Scherbakov has created the modified module that supports a number of additional parameters and features.

Specifically, the “%%S” configuration file variable points to the location of the SFX archive. You may pass it to your application via an environment variable (use System.getenv() to retrieve the value):

;!@Install@!UTF-8!
Progress="No"
SetEnvironment="MYAPP_HOME=%%S"
RunProgram="MyApp.exe"
;!@InstallEnd@!

or via a system property (use System.getProperty() for retrieval):

;!@Install@!UTF-8!
Progress="No"
RunProgram="\"MyApp.exe\" \"-Dmyapp.home=%%S\" myapp.Main"
;!@InstallEnd@!

Notes for the last sample:

  1. It is assumed that MyApp.exe is a multi-app executable, supported in Excelsior JET 7.0 and above.
  2. Notice usage of double quotes around the executable name (required by configuration file syntax when command-line parameters are present) and around the -D parameter (the value of %%S may contain spaces.)

LEGAL

7-Zip and the modified SFX modules are open sourced under GNU LGPL, so changing the SFX modules and using them in proprietary applications is certainly legal. Seek lawyer’s help in otherwise maintaining compliance with LGPL.

TRIVIA

Excelsior Installer uses the LZMA SDK on which 7-Zip is based.

REFERENCES

  1. 7-Zip file archiver. http://7-zip.org
  2. Modified 7-Zip SFX modules. http://7zsfx.info
  3. ResEdit Resource Editor. http://www.resedit.net
  4. PortableApps.com. http://portableapps.com
  5. Portable Application Creators @ Wikipedia. http://en.wikipedia.org/wiki/Portable_application_creators
  6. Excelsior JET User’s Guide.
  7. PCA Changes for Windows 7: How To Tell Us You are Not an Installer, Take 2 (because we changed the rules on you). (Chris Jackson, MSDN blogs)

Article ID: 35
Last Revised On: 08-Apr-2012