9

I'm using launch4j to wrap an executable jar file in my Windows application, but I need to pass references to some of its libraries in through the JVM arguments. The libraries in question reside in the application install directory, and are always located in the same place, relative to the executable.

I'd like to tell launch4j to use executable-relative paths in the JVM options. I know this information is available at the Windows batch script level, but how do you configure launch4j to fetch it?

Edit for clarification: I'm looking specifically for how to make the paths relative to the binary itself, not how to make them relative to the current working directory. The two aren't necessarily the same.

  • 1
    I don't know why you want to call jars via VM arguments from Launch4J launcher. Launch4J can embed them in the executable. Add the names of jars in the *Classpath* list under the *Classpath* tab of the Launch4J GUI. If the jars are under a folder relative to the installation path of the application, prefix each jar with the folder path. For example: the `./lib` folder contains all external jars and the main class is at `./`; so, type `./lib/myexternal-1.0.jar` in the Classpath list. – ecle Feb 28 '12 at 12:35
  • 1
    Because they aren't jars, they are native libraries. As to exactly what I need to load this way, firstly I'm using the SWT browser, and I want it to load a specific XULRunner installation (bundled). To do that, you have to set org.eclipse.swt.browser.XULRunnerPath. Second, there's a native dll used by my own code that I need to load. I want to set java.library.path to do that. –  Feb 29 '12 at 18:51
  • Did you try `System.getProperties().list(System.out)` ("user.dir") and `System.env`? – Joop Eggen Feb 29 '12 at 21:16
  • 1
    Set `-Djna.library.path=` (if using JNA) and `-Djava.library.path=`. Or, you can put this in Launch4J *JVM* options list under *JRE* tab. This is what I do in my projects. – ecle Feb 29 '12 at 22:54
  • @JoopEggen The user.dir property is the current working directory, not the location of the executable. –  Mar 01 '12 at 13:29
  • @eee Yeah, but the problem is I need the path. –  Mar 01 '12 at 13:31

5 Answers5

12

You might add to your launch4j configuration

...
<jre>
...
<opt>-Djna.library.path="%EXEDIR%\\path\\to\\lib"</opt>
<opt>-Djava.library.path="%EXEDIR%\\path\\to\\lib"</opt>
...
</jre>
...

If you need more then a you might seperate several paths by a semikolon as usual.

< opt> Optional, accepts everything you would normally pass to java/javaw launcher: assertion options, system properties and X options. Here you can map environment and special variables EXEDIR (exe's runtime directory), EXEFILE (exe's runtime full file path) to system properties. All variable references must be surrounded with percentage signs and quoted.

Source: http://launch4j.sourceforge.net/docs.html

mhucka
  • 2,143
  • 26
  • 41
vchuravy
  • 1,208
  • 10
  • 22
3

Set -Djna.library.path=<relative path of native libraries> (if using JNA) and -Djava.library.path=<relative path of native libraries>.

Alternatively, this can be done in Java code as: System.setProperty("jna.library.path","<relative path of native libraries>") and System.setProperty("java.library.path","<relative path of native libraries>"). You can append as many paths to refer to. In Windows, use ; to separate the paths.

This setup only has its effect on the JVM runtime of that Java application (not globally like LD_LIBRARY_PATH in Linux.)

Or, you can put this in Launch4J JVM options list under JRE tab. This is what I do in my projects.

ecle
  • 3,952
  • 1
  • 18
  • 22
  • How do I get binary-relative paths though? –  Mar 01 '12 at 13:32
  • In my case, being lazy, I just put the native libraries and dependent jars in the same folder as the executable and set `-Djava.library.path=.\\ ` I even bundle JVM in the same folder and refer it accordingly in my Launch4J script file `jre6` – ecle Mar 01 '12 at 14:37
  • That doesn't work if the binary is called from a different directory. That's why I want binary-relative paths. –  Mar 01 '12 at 14:41
  • @RyanArcher I never encounter any problem in the way I prepare Launch4J script and the application folder structure. Moreover, I use an environment variable to store/retrieve the path to the application in my Java codes. What do yo mean binary: native DLL libraries? – ecle Mar 01 '12 at 14:43
  • If you have binary in another subfolder under the application path, just append the subfolder: `-Djava.library.path=.\\;.\\subfolder` in the same way we set the Windows environment variable `PATH` – ecle Mar 01 '12 at 14:47
  • I mean I want a way to get a path relative to wherever the executable actually is in the file system, as opposed to whatever directory the user currently has open. So if the run time absolute path of the binary is C:\application\bin\app.exe, I want something that will evaluate to C:\application\bin\, even if the executable is called from C:\some\other\directory\. This information is available in windows shell scripts, but I've yet to find a way to get launch4j to give it to you. –  Mar 01 '12 at 15:17
  • You can append `C:\application\bin\ ` into `-Djava.library.path` list and JVM will try to find the binary from the list given that the path is the fixed path to your binary..But, it seems that your path is dynamically set where it is difficult to do so. – ecle Mar 01 '12 at 15:22
  • The batch file variable to get this info is `%~dp0%`, which evaluates to the directory containing the shell script. So for an application where the start script is in `\bin` and the libraries are in `\lib`, you can do `-Djava.library.path="%~dp0%..\lib"` and always find your libraries, regardless of the actual run time install path or working directory. –  Mar 08 '12 at 21:02
  • `%~dp0%` only works in with DOS command intepreter running from DOS command prompt and it doesn't work from inside a JVM. But you can pass this as argument of your application main's `args` entry point and use the command intepreted value of `%~dp0%` as a value in System property `java.library.path`. However, walnus' solution is what you really want which uses Launch4J `EXEDIR` to represent current run directory. – ecle Mar 09 '12 at 01:27
3

One of the options in configuration is to allow a change directory chdir to the executables directory. This will set user.dir to same directory as exe, which you could use to find other application paths.

<chdir>

Optional. Change current directory to an arbitrary path relative to the executable. If you omit this property or leave it blank it will have no effect.

Setting it to . will change the current dir to the same directory as the executable. .. will change it to the parent directory, and so on.

<chdir>.</chdir>
<chdir>../somedir</chdir>

The code which find the actual path to executable will be dependent on OS (readlink, GetModuleFileName etc). Make sure you really test on target OSes..

kamasuPaul
  • 173
  • 1
  • 9
Jayan
  • 18,003
  • 15
  • 89
  • 143
1

If I understand your question correct, you have a launch4j executable and a native library within your installation directory:

/launch.exe
/bin/lib.dll
/lib/app.jar

Now you want to start you app.jar with the generated launcher (launch.exe). You app loads the lib.dll.

You can embed a file into your app.jar (marker.txt). Now you can use the ClassLoader

http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)

getResource("marker.txt);

This will give you something like:

file://c://installdir/lib/app.jar!marker.txt

This String can be parsed. But in fact, I think there should be a better solution for this problem.

Christian Kuetbach
  • 15,850
  • 5
  • 43
  • 79
  • That gets the current working directory, which isn't necessarily where the executable is. –  Feb 29 '12 at 21:04
  • Hmmm, clever. I hadn't thought to use the classloader to get the path. This might work, although I'm a little worried that things won't accept a system property set after Java starts up. I'll have to investigate. –  Mar 01 '12 at 15:03
  • As far as I know, you can't set System.properties via JAVA. They are read-only. In fact you don't need to set them, because you can create an absolute path to your dll and load it (Compare System.loda() and System.loadLibrary() with each others java-doc) – Christian Kuetbach Mar 01 '12 at 15:27
1

You can simply include the directory (e.g. ..\lib) where the libraries are located in the classpath tab in Launch4j. At least that worked for me.

Durandal
  • 19,919
  • 4
  • 36
  • 70