Run exe which is packaged inside jar file - java

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?

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

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.

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

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.

Use
getClass().getResource(what).openStream()
and copy to another file in the disk.

You could write a simple java program to launch the exe using Runtime.exec(). You could then set the "Main-Class" attribute of the jar to be that launcher class. Users could then run your jar and it would run the exe.

Related

When is a Windows folder available to Java's `File#list`?

I have some Java code that does this (on a Windows 10 laptop with Windows Defender on):
unzip a .zip file into a folder (using a zip stream)
immediately list the folder's contents (using File#list)
There are ten files in the zip, from 100kB to 40MB. Normally only the first two files are listed -- the other 8 are silently lost. I know they actually make it to the directory because I can see them when I navigate to the directory myself.
I know there are better ways to implement this code, but I'm curious: is this expected? Is "write file into folder" and "file is listed when you list folder contents" not atomic on Windows? Is it a quirk of the underlying file system? Does Windows Defender make the file invisible for some period of time after it's written?
I am not facing the issue you mentioned and my code is able to list all the files correctly:
package com.test;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipTest {
private static final int BUFFER_SIZE = 4096;
private static String INPUT_LOCATION = "C:/temp/zip/test.zip";
private static String OUTPUT_LOCATION = "C:/temp/unzip";
public static void main(String[] args) throws IOException {
unzip(INPUT_LOCATION, OUTPUT_LOCATION);
for (String s : new File(OUTPUT_LOCATION).list()) {
System.out.println(s);
}
}
public static void unzip(String zipFilePath, String destDirectory) throws IOException {
File destDir = new File(destDirectory);
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
extractFile(zipIn, filePath);
} else {
File dir = new File(filePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] bytesIn = new byte[BUFFER_SIZE];
int read = 0;
while ((read = zipIn.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
bos.close();
}
}

Java UnZipper error?

I'm making a client updater & I'm getting an error in my cmd whilst trying to unzip the file.
What it's supposed to do is:
check if the file exists in the user's home (user.home),
if it doesn't exist in the user's home, check if the file exists in the project's directory,
if it doesn't exist in the project's directory, download the file; if it does, then unzip the file into the user's home.
The error:
Exists in Directory!
file unzip : C:\Users\Ryan T\Desktop\Rezzion Updater\.rezzion.cache\rezzion.cache
java.io.FileNotFoundException: .rezzion.cache\rezzion.cache\Data (The system cannot find the path specified)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at rezzion.UnZip.unZipIt(UnZip.java:54)
at rezzion.Downloader.<init>(Downloader.java:68)
at rezzion.Downloader.main(Downloader.java:78)
file unzip : C:\Users\Ryan T\Desktop\Rezzion Updater\.rezzion.cache\rezzion.cache\Data
Image of Project Folder:
my Downloader.java (Main Class):
package rezzion;
import java.awt.FlowLayout;
public class Downloader extends JFrame {
private static final long serialVersionUID = 1L;
private static boolean exists = (new File(System.getProperty("user.home") + ".rezzion.cache")).exists();
private static boolean existsinDir = (new File("rezzion.cache.zip")).exists();
private static String site = "https://dl.dropboxusercontent.com/s/yoh4d17gfgnv2od/rezzion.cache.zip?dl=1&token_hash=AAE1qdxL_-2y_arb8MBnk8AHSsuhLH1-lwSiGVc0ayQKXA";
private static String filename = "rezzion.cache.zip";
private static final String INPUT_ZIP_FILE = "rezzion.cache.zip";
private static final String OUTPUT_FOLDER = ".rezzion.cache";
private final int BUFFER = 1024;
public Downloader() {
JFrame frm = new JFrame();
JProgressBar current = new JProgressBar(0, 100);
current.setBounds(35, 68, 326, 30);
current.setValue(0);
current.setStringPainted(true);
frm.setVisible(true);
frm.getContentPane().setLayout(null);
frm.setSize(400, 200);
frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
if (!exists) {
if (!existsinDir) {
frm.getContentPane().add(current);
try {
URL url = new URL(site);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int filesize = connection.getContentLength();
float totalDataRead = 0;
java.io.BufferedInputStream in = new java.io.BufferedInputStream(connection.getInputStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream(filename);
java.io.BufferedOutputStream bout = new BufferedOutputStream(fos, BUFFER);
byte[] data = new byte[BUFFER];
int i = 0;
while ((i = in.read(data, 0, BUFFER)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
float Percent = (totalDataRead * 100) / filesize;
current.setValue((int) Percent);
if (current.getValue() == 99) {
current.setValue(100);
}
}
bout.close();
in.close();
} catch (Exception e) {
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component) null, e.getMessage(), "Error", javax.swing.JOptionPane.DEFAULT_OPTION);
}
} else {
System.out.println("Exists in Directory!");
UnZip unZip = new UnZip();
unZip.unZipIt(INPUT_ZIP_FILE, OUTPUT_FOLDER);
//TODO: Exists in Directory
}
} else {
System.out.println("Exists in User.Home!");
//TODO: Exists in User.Home
}
}
public static final void main(String[] args) throws Exception {
new Downloader();
}
/**
*
*/
public static void unzipComplete() {
//TODO
System.out.println("unzip Complete!");
}
}
My UnZip.java (Self Explanatory):
package rezzion;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class UnZip {
List<String> fileList;
private static final String OUTPUT_FOLDER = ".rezzion.cache";
public void unZipIt(String zipFile, String outputFolder) {
byte[] buffer = new byte[1024];
try {
// create output directory is not exists
File folder = new File(System.getProperty("user.home")
+ OUTPUT_FOLDER);
if (!folder.exists()) {
folder.mkdir();
}
// get the zip file content
ZipInputStream zis = new ZipInputStream(
new FileInputStream(zipFile));
// get the zipped file list entry
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator
+ fileName);
System.out.println("file unzip : " + newFile.getAbsoluteFile());
// create all non exists folders
// else you will hit FileNotFoundException for compressed folder
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
Downloader.unzipComplete();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Sorry for the poor formatting of this post, but if anyone can help I've been reading this error for a bit & looking at exactly what it's telling me to, tried merging the classes & no luck. Thanks to those that are willing to point something out, even if it's obvious & I'm missing it.
Since this is apparently a desktop app., the answer seems obvious to me. For deploying Java desktop apps., the best option is usually to install the app. using Java Web Start. JWS works on Windows, OS X & *nix.
JWS provides many appealing features including, but not limited to, splash screens, desktop integration, file associations, automatic update (including lazy downloads and programmatic control of updates), partitioning of natives & other resource downloads by platform, architecture or locale, configuration of run-time environment (minimum J2SE version, run-time options, RAM etc.), easy management of common resources using extensions..
..is there a way I could just keep this?
No.
Using automatic updates, you would abandon all that and simply let the JWS client handle it.
The 'programmatic control of updates' uses an API only available to apps. launched using JWS, specifically the DownloadServiceListener.

Adding ADB to my Java PC application

I have developed a Java application. The application connects to an android device programmatically to transfer some files to connects Android devices.
In my application I have added the adb PATH so it can use it to connect to devices.
I was wondering if its possible to maybe package it within the application ? or just copying the adb into the application directory ? Because I want who ever to download this application, wouldn't need to also have download the adb or Android sdk for the application to work
Is it possible ?
After doing some research you can package an exe within a jar file but you have to extract the exe each run of the application. Following TofuBear's example here I was able to encapsulate adb within a jar file. You'll need to include the AdbWinApi.dll (or equivalent linux libraries).
import java.io.BufferedReader;
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.InputStreamReader;
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 Sandbox
{
public static void main(final String[] args)
throws URISyntaxException,
ZipException,
IOException
{
final URI uri;
final URI exe;
uri = getJarURI();
// Extract the adb application
exe = getFile(uri, "adb.exe");
// Extract the AdbWinApi dll file.
getFile(uri, "AdbWinApi.dll");
System.out.println(exe);
}
private static URI getJarURI()
throws URISyntaxException
{
final ProtectionDomain domain;
final CodeSource source;
final URL url;
final URI uri;
domain = Sandbox.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 = new File(System.getProperty("java.io.tmpdir") + File.separator + fileName);
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();
}
}
}
}
I had to change the file creation from TofuBear's example so that the file name of the exe would not be changed. It's still created in the temporary folder and will be deleted on exit. I left the original code as a comment.
Edit: Seems I got so caught up with the technical possiblity of it I forgot the legal ramifications. It's been stated here by Chris Stratton that the SDK Terms of Service prohibits redistribution of any part of the sdk. Which would include adb.
It should be easier to use the Java-native chimpchat to connect to the device.

SWT-App Loading .swf files from a runnable .jar or external folder

I'm programming using the SWT Widget Library for Java in eclipse, and I'm designing a runnable Java application. I've got the application down, I just don't know how to load external .swf files from a folder on "ALL" computers. I can load Images from any computer, because I use the getResourceAsStream line of code. But the "import com.docuverse.swt.flash.FlashPlayer" "loadMovie(arg, arg)" only takes a String.
So I did ClassName.class.getResource("blah.swf").getPath(); which gives you a string, I set it up, and running it on eclipse it can perfectly find the file in the package. When I export it, the runnable Jar I made cannot find the "blah.swf" inside of the .jar file.
So there is my problem, how do I load my .swf files from within the .jar or from an external folder so clients can download along side the .jar executable application, so it can point to those swf files.
Thankyou.
Here is the way I talked about in comments (creating temp file and save flash animation from jar to it)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.docuverse.swt.flash.FlashPlayer;
public class SWTFlashPlayer {
private FlashPlayer player = null;
private final String FLASH_FILE_PATH = "/EdnCateDance.swf";
private final String TMP_FILE_PREFFIX = "tmp_";
private final String TMP_FILE_SUFFIX = ".swf";
private File swfFile = null;
public SWTFlashPlayer() {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
try {
swfFile = copyFileFromJar(FLASH_FILE_PATH, TMP_FILE_PREFFIX, TMP_FILE_SUFFIX);
} catch (IOException e) {
e.printStackTrace();
return;
}
player = new FlashPlayer(shell, SWT.NONE);
player.loadMovie(0, swfFile.getAbsolutePath());
player.setSize(150, 150);
player.activate();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/**
* Copy file packed inside current jar to temp file
* #param jarPath String - path inside jar
* #param filePreffix String - temp file preffix
* #param fileSuffix - temp file suffix
* #throws IOException - temp file cannot be created or writing somehow fails
*/
private File copyFileFromJar(String jarPath, String filePreffix, String fileSuffix) throws IOException {
File toFile = File.createTempFile(filePreffix, fileSuffix);
// delete file after application finishes
toFile.deleteOnExit();
if(!toFile.canWrite()) throw new IOException("File (" + toFile.getPath() + ") not exists or is not writable!");
FileOutputStream fos = new FileOutputStream(toFile);
InputStream is = this.getClass().getResourceAsStream(jarPath);
if(is == null) throw new IOException("File on jar path could not be located or loaded!");
int read = 0;
byte bytes[] = new byte[1024];
while ((read = is.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
fos.flush();
fos.close();
return toFile;
}
public static void main(String[] args) {
new SWTFlashPlayer();
}
}
I used the EdnCateDance.swf flash file which is one of the examples in SWT Flash library.

java.util.zip.ZipException: Central Directory Entry not found

I have a code which runs absolutely fine on emulator but when I run it on Samsung Galaxy Tab, it gives Exception.
I am receiving one compressed zip file from server via socket and than I am extracting these file. If I compress and send two or three text files it runs fine on both i.e. emulator and Galaxy Tab.
But if I compress and send some small image file with text or two image files it gives: >java.util.zip.ZipException: Central Directory Entry not found < on Galaxy Tab but no error on emulator. Zip file size does not exceeds 32 KB and I am sure that file is being received correctly. Here is my uncompressor code
package com.vsi.vremote;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import android.content.Context;
import android.util.Log;
public class UnCompressor {
private static final String TAG = "UnCompressor";
Context context;
public UnCompressor(Context context) {
this.context = context;
}
private final void copyInputStream(InputStream in, OutputStream out)
throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0)
out.write(buffer, 0, len);
in.close();
out.close();
}
public final String[] unCompress(String name) {
try {
Log.d(TAG, "Uncompress called");
ZipFile zipFile = new ZipFile(context.getFileStreamPath(name));
Log.d(TAG, "Zip file created");
Enumeration entries = zipFile.entries();
String fileNames[] = new String[zipFile.size()];
int counter = 0;
Log.d(TAG, "Loop strting");
while (entries.hasMoreElements()) {
Log.d(TAG, "Getting next entry");
ZipEntry entry = (ZipEntry) entries.nextElement();
Log.d(TAG, "Extracting file: " + entry.getName());
copyInputStream(
zipFile.getInputStream(entry),
new BufferedOutputStream(context.openFileOutput(
entry.getName(), Context.MODE_PRIVATE)));
fileNames[counter++] = entry.getName();
}
zipFile.close();
return fileNames;
} catch (IOException ioe) {
System.err.println("Unhandled exception:");
ioe.printStackTrace();
return null;
}
}
public final void delete(String fileName) {
context.deleteFile(fileName);
}
}
Note: I just checked it on my HTC WildFire, it is also working on this mobile but galaxy TAB :(
Its only adding those file into a zip file (see screenshow) but i have to make a zip file from those zip file parts. I simply devided my zip file into parts and uploaded on the server. now i want to download these files in the my app and rebuild the zip file into the app.

Categories