Run Exe Which Is Packaged Inside Jar File

Run exe which is packaged inside jar file

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();
}
}
}
}

Run *.exe file from inside JAR

Copying the file to a temporary location and running it is the way to go. The answer you linked to does much more work that necessary, as you can get your exe file as an InputStream and copy it to a file with a utility like Apache Commons IO FileUtils.copy(in, out)

See How do I copy a text file from a jar into a file outside of the jar? for example.

How to execute a program within a Jar file

First, some context:

  • A JAR file is an archive, a package (compressed or not) that contains Java bytecode and other resources that can be consumed from inside a JVM.
  • An EXE file is executable binary file that can only be understandable by Windows/MS-DOS family OSs.

When you run your program without packaging it into a JAR file, all resources (the class file and the executable) are accessible from the OS. Windows will launch the JVM and from inside there you, by means of the ProcessBuilder, instruct the OS to invoke an executable file accessible in a path which is relative to the class performing the execution instruction. Until there, everything is fine and as you said, it works.

However, when you pack your Java class and the executable file in a JAR and invoke the JAR, its contents are no longer accessible for the OS. What is happening is that the OS will launch the JVM and it will process the JAR file to find the executable class (the one in which you invoke the ProcessBuilder). From that class file you now instruct the OS to launch an executable which is in a path relative to the JAR file instead of being relative to the class file performing the invoke instruction. Since the EXE is inside the JAR file instead of being relative to it, execution fails because it can't find the executable.

This is that way because the OS won't look inside the JAR file for a specific file, for the OS the JAR file is just that, a file, not a folder so it will ignore its contents.

So, the conclusion is that, since you are invoking the OS to perform a specific operation in another file, just must place that file outside the JAR and in a relative path to that JAR.

If for some reason you insist on packaging your EXE inside the JAR, then you need to extract it outside the JAR before invoking the ProcessBuilder to a temporary folder and invoke the ProcessBuilder using that new path.

How to run .exe file within program

Lets imagine a File f = new File(Path);

If in that case we have the file inside our project (same directory),then we dont need to add the path, just the file name and extension (ex: .txt)......I guess in your case it would be something similar.



Related Topics



Leave a reply



Submit