Run exe which is packaged inside jar file
Solution 1
This will extract the .exe
to a local file on the local disk. The file will be deleted when the Java program exists.
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class Main
{
public static void main(final String[] args)
throws URISyntaxException,
ZipException,
IOException
{
final URI uri;
final URI exe;
uri = getJarURI();
exe = getFile(uri, "Main.class");
System.out.println(exe);
}
private static URI getJarURI()
throws URISyntaxException
{
final ProtectionDomain domain;
final CodeSource source;
final URL url;
final URI uri;
domain = Main.class.getProtectionDomain();
source = domain.getCodeSource();
url = source.getLocation();
uri = url.toURI();
return (uri);
}
private static URI getFile(final URI where,
final String fileName)
throws ZipException,
IOException
{
final File location;
final URI fileURI;
location = new File(where);
// not in a JAR, just return the path on disk
if(location.isDirectory())
{
fileURI = URI.create(where.toString() + fileName);
}
else
{
final ZipFile zipFile;
zipFile = new ZipFile(location);
try
{
fileURI = extract(zipFile, fileName);
}
finally
{
zipFile.close();
}
}
return (fileURI);
}
private static URI extract(final ZipFile zipFile,
final String fileName)
throws IOException
{
final File tempFile;
final ZipEntry entry;
final InputStream zipStream;
OutputStream fileStream;
tempFile = File.createTempFile(fileName, Long.toString(System.currentTimeMillis()));
tempFile.deleteOnExit();
entry = zipFile.getEntry(fileName);
if(entry == null)
{
throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName());
}
zipStream = zipFile.getInputStream(entry);
fileStream = null;
try
{
final byte[] buf;
int i;
fileStream = new FileOutputStream(tempFile);
buf = new byte[1024];
i = 0;
while((i = zipStream.read(buf)) != -1)
{
fileStream.write(buf, 0, i);
}
}
finally
{
close(zipStream);
close(fileStream);
}
return (tempFile.toURI());
}
private static void close(final Closeable stream)
{
if(stream != null)
{
try
{
stream.close();
}
catch(final IOException ex)
{
ex.printStackTrace();
}
}
}
}
Solution 2
The operating system doesn't care or know about .jar file, so you'll have to unpack the .exe
file to some temporary location before you execute it.
Solution 3
//gets program.exe from inside the JAR file as an input stream
InputStream is = getClass().getResource("program.exe").openStream();
//sets the output stream to a system folder
OutputStream os = new FileOutputStream("program.exe");
//2048 here is just my preference
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
Solution 4
Whilst the other users have answered the question correctly, extract and run then cleanup. Another point to consider is going fully native.
You are already using a native binary to achieve a specific task. Why not also create a native installer which will install your application, and install the binary to the OS specific location (Program Files on Win32) and create suitable shortcuts.
This way your application will feel more native and means you don't need to write or manage code to get around this fact. At the moment the Jar looks like a cross platform piece of code (Jar runs anywhere right?) but packs a native binary which will not run everywhere. This feels like a contradiction.
For installers I can recommend Nullsoft Installation System (NSIS) as they have many excellent tutorials and code samples to learn from.
Solution 5
Use
getClass().getResource(what).openStream()
and copy to another file in the disk.
Comments
-
krisp about 4 years
I am executing an exe through my java program. The path is hardcoded in Java.
I have packaged my the exe in the jar.
But am stuck as I have the path name hardcoded in the Java file, so I am not able to execute my jar as a stand alone program.
Any hints for packaging such jar i.e having an exe inside and able to run it as a stand alone program?
-
krisp about 15 yearsIn this case i will require to hard code the exe path in java code. I want to make it portable.
-
Kevin about 15 years@Krisp. Not true. You can use Class/ClassLoader.getResource() to find a relative path within the jar
-
Michael Borgwardt about 15 yearsThis can't work - Runtime.exec() tells the OS to execute something, and the OS can't execute something inside a JAR file.
-
Kevin about 15 years@Michael He can extract the executable to a temporary directory and run it from there.
-
Sandeep Chauhan about 15 yearsDont forget to set the executable flag, otherwise your code works on Windows only.
-
gencoreoperative over 12 years+1 for creating a temporary file and marking it delete on exit.
-
Andy over 10 yearsI know this is an old question, but I'm trying to use code similar to this with Windows 7, but I can't execute
.exe
s in the temp directory. Would appreciate it if you could check out my question: stackoverflow.com/questions/18559835/… -
Markus Malkusch over 6 years@gencoreoperative actually that's a can of worms which if done in a wrong context can easily create a memory leak.
-
hipokito about 6 yearsI copied the file from resources to the root directory of the project using the method D.Snap described and I am now referring to the file like so: "File file = new File("your.exe");". So you can open the file for writing to root directory from resources directory (if you are using a maven project) like so: "InputStream is = getClass().getResource("your.exe").openStream();"
-
ParisaN about 6 yearsPlease describe your code. What is
FileOutputStream
? I test but does not work. -
m4heshd almost 6 yearsRemember, using this method will more likely get your app flagged by the AV.