Java: Copying an exe-file and launching afterwards fails - java

I want to copy an existing .exe-file from one directory to another and launch it afterwards with Java. Like this:
FileIO.copy( new File( sourceFile ), new File( targetFile ) );
System.out.println( "Existing: " + new File( targetFile ).exists() );
System.out.println( "Launching " + targetFile );
String cmd[] = { targetFile };
Process p = Runtime.getRuntime().exec( cmd );
p.waitFor();
System.out.println( "Result: " + p.exitValue() );
The output is like this:
Existing: true
Launching C:\test\Launcher.new.exe
Result: 2
So Java says that the file is valid and existing, but Windows just can't launch the process because it thinks the file is not there. The pathes are absolute and with backslashes. I also have all permissions on the files so I'm allowed to execute them.
The Launcher.new.exe is generated by Launch4j, so it's more or less standalone. At least it doesn't depend on DLLs in the same folder. But strange: It works when I copy and launch the notepad.exe.
One more strange thing: If I don't copy the file by Java but by hand, the launching also fails with the same error.
OS is Vista with SP1.
Any clue?

Hmm... I wonder if this might be Vista's wonderful User Access Controls at play...
Are you working within Program Files? If so, move everything out into a seperate folder (c:\CopyTest) and try again - see if that helps...

Without more details, it's hard to give specific answer. Check your permissions on the c:\test directory and the permissions on target file you are trying to execute.

If your path contains forward slashes, you might want to try changing them to backslashes before execing. Also, you should try to make the path absolute, including a drive letter and colon (e.g. C:\test\myprog.exe). Note that if you code the path in a Java String, you need to double up the backslashes...
Once you get that working, you can ease up on those constraints until you figure out what broke your attempt.
EDIT 1: Some common pitfalls with exec() are mentioned in this article. I don't think any of these apply, but you may want to use the coding from the last example to run your .EXE within CMD.EXE to get decent path resolution, error handling and such.
EDIT 2: Your executable file name needs to be interpreted as a long file name. I'm not positive the API can/will handle this. Please try giving the .EXE a short, simple name (just for testing) like NEWPROG.EXE (with no second dot in the name, either!) But first definitely give it a try with CMD.EXE first.
EDIT 3: From reading comments to the other answer: Is it possible your program is indeed running, and itself returning a status of 2 because it is failing to find a file? Is there some way to verify operation of your program, perhaps by calling it from a .CMD batch script that you run from your Java program, and having it write output redirected to a file?

Maybe the problem you might me facing is not having the bundled more in the directory. Launch4j may convert your program to exe, but there just be a local directory to the jre. That folder contains the bin and lib files of any existing Java jre.
Maybe it helps...
Update
Seems like some people are having a tough time understanding what I said. No problem, I'll explain.
Let's take an example that I have created a simple Client Chat App in Java and I exported it into a runnable .../ClientChatApp.jar file. Yet, it still doesn't have the dependencies within it to run the file and needs the installation of Java in the desktop for doing so. For example here, .../ClientChatApp.jar still needs the dependencies of javax.swing.*, java.net.* and java.io.*. Hence it will locate those dependencies from the JDK/JRE it is supposed to use.
Now, when it comes to converting from .../ClientChatApp.jar to .../ClientChatApp.exe, it will work as expected, only if the desktop has Java installed, so that it can collect the dependencies from there. This is not user friendly since any user who doesn't have Java installed will have to install it first to be able to use your app.
Here's where Launch4j helps. When you are converting from jar to exe using this program, then it helps to redirect where the exe will look for the dependencies in a local folder, usually being .../jre/... in the sam directory as the .../ClientChatApp.exe file. Quick tip: To actually do that, go to the same directory as where you want to have the exe file, create a folder there called jre. Now go to C:/Program Files/Java/<<your JDK or JRE folder>>/ and then select and copy the bin and lib folders and copy them. Then go to the directory where you created the folder of jre and paste both of the folders in the folder.
Many users may have already done it, but why I explained all the above is to give a clear understanding of what the jre folder does and hence come to the main point, that you will have to also send the jre folder with the exe file to the user, otherwise there is a point of failure while execution.
You can send them into a .zip file or create an installer exe using Inno Setup. I recommend doing more research if you're wanting to use Inno Setup.
That's it. Thank You! (plz upvote me, its my first answer)

Related

Java Jar file main class run when runs from command line, but not from Windows batch file

I'm re-using a standalone Swing-based Java class which backs up and restores mysql databases.
I've tested running it from a Windows batch file (.bat) on my dev system, and it works there.
But, if I run the batch file on a different Windows , I get a "main class not found" exception.
However, when I run the command directly on the command line, it works.
The command in the batch file to run it is:
java -cp lda-services.jar;bip-services-1.6.0.0-SNAPSHOT.jar;decryptor-1.6.0.0-SNAPSHOT.jar;slf4j-api-1.7.31.jar;commons-io-2.6.jar com.ilcore.util.SosaMaintenanceJFrame
The SosaMaintenanceJFrame class is contained in the lda-services jar.
Here's the error message:
Error: Could not find or load main class com.ilcore.util.SosaMaintenanceJFrame
Caused by: java.lang.ClassNotFoundException: com.ilcore.util.SosaMaintenanceJFrame
The class is definitely in the jar file, as I've extracted it the file and seen it.
Any thoughts on why this would be happening? I need to run inside a batch file so the user can just click on it to run it.
Most likely explanation
Your paths are relative, which means that the batch file isn't going to work unless you run it from the right place. In general, having a batch file that has an invisible rider stapled to it with: "I break in mysterious ways if not run from the appropriate dir" is a crappy batch file - make it better.
Better solution
Or, even better, get rid of it. You don't need batch files to distribute java programs.
Proper ways to distribute java programs:
The modern take is very very different from what you have here: JREs are dead, you must ship an installer that does the whole thing, notably including a java runtime (no longer called a JRE, and one you ship and keep up to date if relevant). That's perhaps a bridge too far for what you're doing here. Relevant tools include jlink.
A slightly less modern take involves jars with manifests:
Your jar file should contain a manifest. This manifest must contain 2 relevant entries:
Class-Path: lda-services.jar bip-services-1.6.0.0-SNAPSHOT.jar decryptor-1.6.0.0-SNAPSHOT.jar slf4j-api-1.7.31.jar commons-io-2.6.jar
and
Main-Class: com.ilcore.util.SosaMaintenanceJFrame
You can use jar's -m switch, or just include the manifest (it's just a file in the jar): it's at META_INF/MANIFEST.MF and it's a text file, each line is an entry, and an entry consists of a key: value pair.
When a jar contains this, just double clicking the jar and running java -jar thejar.jar will then take care of it all: Java will load the stated jars as part of the classpath, and these, crucially, are resolved as paths relative to the directory the jar is in, so it DOES work when you try to launch them from elsewhere, i.e. if you do:
C:
CD \
java -jar "c:\Program Files\MyApp\myapp.jar"
it works fine, whereas that batch script would fail due to being in the wrong place.
Build systems let you define the manifest too, check your build systems docs for how to do this, it'll be easy, and there are tons of tutorials if you search the web for e.g. 'manifest executable jar maven' or whatnot.
You can consider making a shaded jar. But I wouldn't.
A shaded jar takes all your dependencies and packs them into your main jar, so that there is only one jar. There is now no need for a Class-Path entry (the jar you run is obviously already on the classpath and there's nothing else to include) and your app is shipped as 'just' a single jar file.
But this is mostly a red herring: There are no consumer JREs anymore so you've made the user experience from a D- to a D. If you actually care about giving your users a nice experience, there's no getting around an installation process of some sort and once you have that, having the separate jars is no longer a problem. Separate jars are less hairy when signed jars are involved, are much easier to keep up to date, and have a significantly faster turnaround (when you build your stuff and want to ship what you built, shading takes ages, so it's nice to cut that step out). The faster your CI system tells you about failing tests, the better.
Meet in the middle
You don't have to upgrade to modules and the like. What you can do instead is use something like launch4j. The aim is to end up with a zip file along with the installation instructions: Make a dir somewhere. unzip this zip in it. Doubleclick 'myapp.exe'. Done.
The zip would contain an entire JRE, all your jar file deps, and your main app, and an exe file which launch4j made for you, that launches your app using the JRE packed into the jar. This means you know exactly which JRE is being used, and it'll work even on systems that didn't have one installed yet (which, these days, should be all of them - the notion of 'end user downloads a JRE from oracle and the user + oracle work together to keep that thing up to date and security-issue-free', is dead).
The fact that it's an EXE is nice: Now if the user e.g. alt+tabs through their apps, they get your app, with your name, and your icon, instead of 'javaw.exe' with an ugly coffee mug logo.
But when I try running it from the jar file generated by Maven, however, I get a "class not found" exception.
Even if you didn't get that error, you'd get another one unless you'd used Maven Shade, as that's the only way you're going to run that with a single jar. My guess as to why that particular error occurs is that the app class you're attempting to run is in fact in one of the *SNAPSHOT* jars

How to run or call an exe file from a JAR file which is present in the same directory?

Hello all :) I love stackoverflow where I always find answers but this time I could not so personally asking... Its bit lengthy please go through it.
I am creating a java application where one of my resource is an exe file which I need to call in the java code. But later I would convert the whole java code to a JAR file... and I would add the JAR file and the exe file for the Setup file for installation process. So when I extract the files I want my JAR file to call the exe file while running... I am doing this all in Eclipse :)
So my doubt comes here which path I should put up in the java code... ? So that it will always call the file the exe file from the same directory where the JAR file is also present.. :)
Any help would be great :) Thank you in advance :)
Assuming that you control the whole installation process; and that you also control the script that later starts a JRE to run your JAR within; my suggestion would be: simply use a property here.
In other words; your installer knows that it copied JAR and EXE to D:\example\ for example. Then just make sure that your JAR is started like:
java -jar D:\example\your.jar -D your_path=D:\example
(this is just meant as example, you would have to work that out, probably the \ in there need some special treatment for example)
Then your application can simply query for that system property "your_path" and take the value from there.
Alternatively, you could try this solution that works "pure java".

How to change the working directory of a bundled Java program

I wrote a program in Java and packaged it up as a Mac App using Netbeans. It has the typical Java, MacOS, Resources, and Plugins folders and works just fine. The problem is that my program has a save feature which, whenever used, saves files to the computer's User directory instead of the directory in which the program itself is running—the Java folder.
In the past I got around this with a custom executable containing the lines
# Set the working directory
DIR=$(cd "$(dirname "$0")"; pwd)
cd $DIR
But since Netbeans creates the executable now and encodes it in some unreadable way, that's not an option. I would use the old one but Netbeans adds the benefit of bundling a JRE with the program so I'm stuck having to choose between saving in the right spot or bundling the JRE.
Does anyone know how to change the working directory of a packaged program?
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
EDIT:
I took Tyler's advice and decided to find the directory I wanted within the program itself instead of trying to change the PWD with scripts.
Say you're running a Jar file by double clicking it or using terminal/cmd (This only works by directly running, not through ANT or an IDE). This will give you the directory that your Jar is in:
String path1 = MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String path2 = (new File(path1)).getParentFile().getPath();
String PWD = URLDecoder.decode(path2, "UTF-8");
The first line gets the path to your Jar file.
The second line
removes the name of the Jar from the end, leaving you with the
directory it's in.
The third line accounts for special characters
like spaces.
I'd use something like
System.getenv("HOME");
to find the user's home directory instead of changing Java's working directory.

Java program is loading from system32 folder, not from folder, which it is placed

I wrote desktop program in Java on Windows 7 and hanged it on startup by writing to registry the path of jar file (kind of C:\Users\User\Documents\My App.jar) in HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Run branch. When my program loads with Windows, it must load some text file that placed in the same folder as the program:
File f = new File("text.txt"); // without full path to file
if(!f.exists())
JOptionPane.showMessageDialog(null, "File not found: " + f.getAbsolutePath());
but cant do it and I get message: "File not found: C:\Windows\system32\text.txt". It appears as if the program is located in the system32 folder and a text file, respectively, too. What did I do wrong?
My theory: if you installed Java for Windows via the traditional installer, in addition to the place you told it to put it (canonically, JAVA_HOME), the installer drops a java.exe in the system32 directory, so it's likely that when you're starting the JVM on startup, system32 is the working directory and that's where it will look for files with relative path names like the one you've provided.
The easiest solution is to specify the path to the text file absolutely in your code. I would also recommend specifying the full path to java.exe in your registry key (I would guess that right now it's just java.exe with no path) so that you can guarantee which version you're running; if you have multiple versions of Java installed only the most recently one installed will have java.exe in system32 and without a qualifying path I would guess that's the one you're getting since PATH will probably be minimal at that point.
As a closing--unrelated to your problem--point, I hate that Java does this on Windows and wipe that copy of java.exe out immediately, and then set up PATH to make sure the version I want is the one that is executed on demand.
You need to get current working directory and use it as a part of absolute path to a file.
Take a look at this question: Getting the Current Working Directory in Java
The other workaround would be to read this registry key you described and using this information to read a file from desired path - read/write to Windows Registry using Java
The path that you are referring is the working directory, and is not where the application is installed. Like if you put a shorcut to it, you can change the working directory and it will change the result you are getting. But as you put it to startup automatically, probably windows is setting this as the working directory.
Like that:
Use registry to startup a program, and also change the current working directory? 1
You can try to pass the file directory to your app with a command line parameter in the registry.
1 - This probably won't solve the problem for you, don't seems you have one, its just an explanation
I think that #Omaha's answer is describing what is going on (you are launching java.exe from the system32 directory - the JRE installer places a copy of java.exe in system32 to make it easier for users to access).
The actual solution to your situation is to adjust your CurrentVersion\Run registry entry so it specifies a default working folder for the application. Check out: Use registry to startup a program, and also change the current working directory?

How to get location of runnable .jar File when run from GNOME

I am developing a small Java application using Swing, that is supposed to run on Windows/Linux and MacOS.
Eventually it will ship as a runnable jar with some config files in the same folder. To load them I need the path to the folder the jar is stored in within the program.
There are already a couple of threads like this one or this one.
My problem is, that all the solutions discussed there work fine, when I run the program from within eclipse or call the runnable jar from a terminal like so:
java -jar /path/to/jar/jarfile.jar
However when I click on the jar file in Cinnamon or Gnome (which is what most of the users will know to do), I do not get the correct paths. (MacOS users report the same issue)
Here is what I've tried so far and what the output is when run via double click (all those display the desired path when run from eclipse or a terminal):
ClassLoader.getSystemClassLoader().getResource(".").getPath()
Output: file:/usr/lib/jvm/java-6-openjdk-common/jre/lib/ext/pulse-java.jar!/
SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
Output: ./
System.getProperty("user.dir");
Output: /home/myusername
Is there any other way to do it or am I doing something wrong when exporting the jar? Any help would be appreciated!
Cheers
Nick
Make it simple, and use a startup script (.bat/.sh file) to run your application. This startup script will get the path of its own location in the filesystem, and pass it as an argument or system property to the Java application. This has the additional advantage of being able to pass other arguments, like the size of the heap, etc.
On windows, %~dp0 is the path of the directory containing the executed bat file. On Unix, you can use $(dirname $0).
You could store all config files as resources in a jar, and copy them to files in home.dir + ".AppName/".
Painful as it is, the Preferences API, Preferences.systemNodeForPackage, seems the wisest alternative, if there is little structured config data. There is an inputStream method for import; your initial config template could be a resource in the jar.
Just get the class path using System.getProperty("java.class.path") and scan it for your ".jar" name. Note that path separators are OS dependent (File.pathSeparator)

Categories