Launch4j seems to simple to setup but after the exe has been generated it wouldn't run from another location.
The jar file used to create the launcher still needs to be in the same folder as the exe is.
I thought it would have wrapped the jar in exe and could run it from anywhere? I have done this with JSmooth before and it worked well. But JSmooth isn't supported on Windows 7 anymore.
Also could not find any proper documentation for it.
What is going wrong here.
Thanks,
Shankar.
Your simple scenario works for me. The only options I needed to fill in were Output file, Jar and Min JRE version. Everything else is left as default.
It's important to have all your external libraries packed into the JAR and not into a folder next to the generated JAR. To achieve that, select "Extract required libraries into generated JAR" option in Eclipse when exporting runnable JAR.
If we are talking about the JAR containing the main class, then this is configurable: http://launch4j.sourceforge.net/docs.html#Configuration_file
What you want to set is dontWrapJar to true, but this is the default value so you had to change something if it's not in the EXE. When toggling this boolean, one can clearly see the size difference (e.g. in my case it's 40K without JAR and 56 with 16K JAR included, also in Total Commander I can use Ctrl+PgDn to enter the EXE as any other ZIP if it has JAR included).
In POM file when using com.akathist.maven.plugins.launch4j:launch4j-maven-plugin plugin the option is named the same - dontWrapJar. In that case jar option must point to the built JAR (in target), because it is relative to EXE (and both goes to target) in most cases it's just the name of the JAR. While the JAR is lying next to the EXE, it is not necessary to run the EXE and can be removed to check it.
This does not tell anything about other dependencies for which there are other options and if you need everything in EXE than you need to use some uberjar solution.
Related
I have a legacy app that I'm porting from Ant to Maven. My Maven build works fine for the main project, which I've moved into the standard Maven directory layout (*.java files in /src/main/java/) and it outputs the compiled classes into /target/classes/ as neat as you could wish. These are packaged in a .war file.
However, the project also has a class outside of the folder hierarchy, indeed outside of the web application, that contains scripts that run via cron job. Let's say it's /cronjobs/MyClass.java. I need that class to be compiled and output to /target/cronjobs/MyClass.class and zipped up as part of the resulting .war file, in its /cronjobs/ folder.
Can Maven do this? I know it's possible to change the default "src" directory and "target" directory, but I don't know if (or how) it's possible to run a separate, parallel compile step for just one class.
I can move the source file, of course, if it's easier to compile it with the other classes and then move it later (maybe with the WAR plugin?) but I definitely need the compiled MyClass.class file in the /cronjobs/ directory of the .war.
I'd split the project in 2 parts, webapp as war and cronjobs as jar. Maven knows about multi-module format and it is somewhat the best way to go forward and decouple the webapp from non-webapp code.
Please note: I have created this GitHub project right here that can be used to perfectly reproduce the problem I'm seeing.
Java 8 here attempting to use Launch4J via the gradle-launch4j Gradle plugin to build a Windows native EXE application. I am doing the development of a Java Swing app on my Mac but the app must run as a Windows EXE on Windows 10. I am also using ShadowJar to build my self-contained "fat jar".
I can build my (Swing) app's fat jar and then run it on my Mac via java -jar build/lib/myapp.jar. It starts and runs no problem.
Here is my Gradle config for Launch4J:
launch4j {
mainClassName = 'com.example.windows.hello.HelloWindowsApp'
icon = "${projectDir}/icon.ico"
jdkPreference = 'jdkOnly'
initialHeapSize = 128
jreMinVersion = '1.8.0'
jreMaxVersion = '1.8.9'
maxHeapSize = 512
stayAlive = false
bundledJre64Bit = true
bundledJrePath = '../hello-windows/jre8'
}
When I run ./gradle clean build shadowJar createExe createDistro it produces:
hello-windows.zip/
hello-windows.exe --> The Windows EXE built by the 'createExe' task
lib/* --> The lib/ dir for the EXE that is also built by the `createExe` task
jre8/ --> OpenJDK JRE8 (copied from the libs/jre8 dir)
So I copy that ZIP file and port it over to a Windows 10 (64-bit) machine. I extract the ZIP and run the EXE by double clicking it inside Windows Explorer (which I can confirm does see the EXE as an Application type). First I see this:
Why is this happening? Are there any Launch4J configurations/settings I can change so that this doesn't happen?
Thanks in advance!
You need to sign the executable created by launch4j as described here to prevent SmartScreen from blocking it to be run. See also the related discussion in the support forum.
Your first question is more like a Windows question. When you unzip an application from a zip file, Windows will naturally mark it as unsafe, in fact if you check the application properties tab, you will see a checkbox where you can remove that unsafe attribute. It's same as running chmod+x for an executable script in Linux.
For the second part, I assume you are using the gradle plugin for Launch4j, there are two main ways to configure Launch4j assuming your project folder is structured commonly with the jre library in the same folder containing your executable folder.
By specifying the path only like
../jre
By specifying the full relative path
../jre/bin/javaw.exe
Your generated xml at the end should look like this in the first case.
<jre>
<path>../jre</path>
</jre>
The main point is that the path to JRE is relative to the position of the executable not the current directory. In this case, we step back one directory from the executable folder to the folder containing jre.
Try setting the bundledJrePath in your build.gradle to just jre8:
launch4j {
...
bundledJrePath = 'jre8'
}
Because that is in your case the relative path where the jre is when extracting the zip.
http://launch4j.sourceforge.net/docs.html
<path>, <minVersion>, <maxVersion>
The <path> property is used to specify the absolute or relative path (to the executable) of a bundled JRE, it does not rely on the current directory or <chdir>. Note that this path is not checked until the actual application execution
Beware that the path must not contain the /bin/javaw.exe.
When running the exe with the debug flag like this
hello-windows.exe --l4j-debug
then it will create a file launch4j.log in the same directory.
There you can check that the correct jre is picked up, for example:
...
Bundled JRE: jre8
Check launcher: C:\Users\IEUser\Downloads\hello-windows\jre8\bin\javaw.exe (OK)
...
I upvoted the answer above from sschuberth, as that is the best answer to your question. Signing the executable will make SmartScreen happy.
As addition I would rather prevent trying to create an executable, even signing it, best to create a MSI. For example by using Javapackager. See also this question. That guy created his own tool after using Nullsoft.
It is very cumbersome to get an executable accepted by every virus scanner around the world. I have the experience of using WIX Toolset to create an MSI and wrapped it into a bootstrapper executable, signed it using the company signing certificate. However in the end I had to send requests to McAfee, Norton, Avast, AVG, KasperSky and Trend Micro. Gladly all accepted it over time, only Trend Micro never even responded.
Would like to disable the test-out folder means test outputs in my project as it less disk space issues in automation machines. Tried all below options as got it our tool:
SetDefaultListener(false);
setVerbose(0);
command line argument -usedefaultListener false
nothing can work me.I am using maven build tool to generate the jar. We need to give the jar to automachines to run this.
That's not possible by definition if do not want to have that folders, you have to skip tests in process of Jar building.
For my OSGi development i have setup a target definition (.target file) which references two directories. Eclipse picks up all the jar files inside these directories and adds them to the target platform. But one of the bundles i have is a WAR file (.war extension) which is run using pax-web. Eclipse doesn't show this in the list of bundles available. Is there any way to add a particular bundle directly into the target definition? Any way out that i might be missing?
One workaround i found was to rename the .war file to .jar. Pax-web doesn't care about the extension, eclipse picks it up and so everything runs fine. But i am not very convinced if this is the right solution.
Thanks.
Bug 355890 was fixed for 3.8/4.2. You can now include archive files that are not jars (i.e. WAR files).
There is a known bug filed on eclipse on this very issue. Until it is fixed, the only workaround is to rename the file to have the .jar extension.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=355890
My work project needs to be compiled and run under JDK1.5 and I'm on a Mac. I followed the instructions here to get 1.5 back on Snow Leopard, and it works fine when building from IntelliJ IDEA, or if I'm just in the same directory as the build.xml and try "ant CleanRebuild" When I "Run Target" in NetBeans they're all compiled with the wrong version resulting in
java.lang.UnsupportedClassVersionError:
Bad version number in .class file
(unable to load class...
when tomcat is trying to start up.
So things I've tried
Set the "Java Platform" to 1.5 under the project properties/libraries.
Set the Source/Binary Format to JDK 5 under project properties/sources.
Pointed the ant home to the ant I'm using under preferences/ant
Renaming every javac executable I could find in the hopes NetBeans would fail to compile and I could figure out which one it was using (no luck)
Setting 1.5 as the default, resulting in the need to point $netbeans_jdkhome to the 1.6 jdk in order for NetBeans to even start.
All unsuccessful....
Again, if I cd into the directory of the netbeans project with the build.xml and run the command manually all is well....so NetBeans. What's the deal?
Revised answer
Assumptions: NetBeans version 6.9.1 (although likely applicable to most or all 6.x versions), alternative build systems (e.g., Maven) are not used...the default (Ant) is used.
NetBeans, by default, uses Ant as its build system for doing things like compiling a project, building a project, cleaning built files from a project, etc. Ant has two concepts that are applicable here: targets and tasks. A target, in Ant's vocabulary, is simply a "command" or a series of jobs that need to be completed for a particular job. In NetBeans, common targets are "Compile", "Build", "Clean and Build", etc. The "jobs" that a target completes are (among other things) Ant tasks. In NetBeans one task (which is particularly relevant in answering this question) is the Javac Task. This is the task that Ant uses to compile .java files into .class files.
An Ant-based project, and therefore a NetBeans project, uses the file build.xml to control the build process and tell Ant how to go about accomplishing the targets. In a NetBeans project, the build.xml is found in the root directory of the project, by default. NetBeans, however, uses a user-extensible build.xml file. The core targets and tasks defined by NetBeans are actually located in nbprojects/build-impl.xml and imported into build.xml within the first few lines of the file. The theory is that users can add or override things in build.xml while the core NetBeans-defined configuration remains untouched in the build-impl.xml file.
If you look in the default nbproject/build-impl.xml file for a NetBeans Java project, you will find the Javac task referred to twice. (Search for "<javac".) Both are in macro definitions, and therefore deep within the complexities of NetBean's default build configuration. If we refer to the Javac Task documentation we find that the tasks uses the compiler in the location specified either by the global build.compiler property, by the compiler attribute specified with the <javac... /> task, or the default which is the Java compiler that is used when running and, and thus the one that is used when running NetBeans (because it is what fires off the Ant process). Since we don't see build.compiler or the compiler attribute anywhere (in the default build-impl.xml), then we can only conclude that the default is being used.
So here we have the (more-or-less correct) first answer. NetBeans compiles using the JDK that was used to execute NetBeans by default. It looks like it is actually a bit more complicated than that simple answer, but it is essentially correct. If you look at the documentation for the Javac Task it alludes to "a class that implements the CompilerAdapter interface", which suggests that rather than calling the javac executable directly, Ant (and therefore NetBeans) compiles using the compiler class (that, in all likelihood, the javac executable also uses). Refer to the Original answer below to determine which JDK what used to run NetBeans.
So, what if you don't want to use the default JDK that was used to run NetBeans? This is where "Java Platforms" comes in. Go to the Tools menu, and click on "Java Platforms". You likely only have one platform defined here. (As an aside, this is actually the most correct answer to what JDK is used by default... the one defined here in the Java Platform Manager.) If you would like to compile against another Java version (say your default JDK is 1.6, but you want to compile against 1.5) then you would install the alternate JDK somewhere on your system, and then configure a platform here in NetBeans' Java Platform Manager. (I'll leave it as an exercise for you to find the documentation on how to add a Java Platform. A superficial search of the wiki didn't turn up anything obvious. In any case, it's fairly self-explanatory.)
Once a new platform is created in the manager, you would right-click on your project in the Projects tab, click on "Properties", and then on "Libraries". At the top, you would select the appropriate Java platform for the project. As soon as you change this value and click on "OK", NetBeans makes several adjustments to your build-impl.xml file that point it to the new JDK against which to compile. (It is instructive for the truly geeky amongst us to make a copy of the nbproject directory before making this change and to diff that against the new contents of the nbproject directory after the change is made.) The changes instruct the Javac Ant Task to use the (equivalent of the) javac executable of the specified platform. So here we have the most correct answer: NetBeans uses the equivalent of the javac executable (as invoked by the Ant javac task) that is specified in the project's Java Platform located under the Libraries node of the project's properties.
Original answer
The path to the JDK used by NetBeans can be found in the netbeans.conf file. Look for the netbeans_jdkhome entry.
You can also specify the jdkhome at runtime (*NIX example given):
netbeans --jdkhome /usr/bin/jdk1.6.0_22
The netbeans.conf file is found in different places depending on what OS you are using. See the NetBeans.conf FAQ on the NetBeans wiki for help finding the file.
A few additional comments...
...You can specify the -target option in the project properties. In NetBeans 6.9 right-click on the project, and choose Properties. Click on the Compiling node. Add your -target to Additional Compiler Options.
...I have read in a few places that specifying a target is not a guarantee that the code will run on a JRE whose version is lower than the JDK that built it. In other words, the recommendation seems to be that if you want 1.5 binaries, then compile with the 1.5 JDK.