Windows file association and single instance of Java program - java

I have a Java program that I've made which opens and uses .project files. As long as I open the files from within the program everything works fine. However I want to be able to install the program and register (maybe even maintain) file association so that when the user will double click on a .project file one of two things will happen:
If the program is not running, the program will launch and will have the file path (complete with name and extension) passed to it so it could open the clicked file.
If the program is already running, do not open a second instance of the program but rather pass the file path (complete with name and extension) to the program so it could open it.
I've scoured the internet and found things such as:
The Java™ Tutorials
and
Stack Overflow - inno setup file association
but these answers are confusing. They talk about using external programs (is this necessary?) and don't explain properly how to accomplish file association in them or talk about Ant code while building in Netbeans (which I am using) but I don't really understand how to start Ant code, if I need to add it, add a new .xml file to the project or whatever.
I've tried manually associating my built JAR file in the Windows association list but it will not accept it. I am guessing I need it installed and/or converted somehow into an .exe.
In any case I want to distribute the program to others and so it needs to be done automatically.
I would prefer to have this work on multiple platforms but I am most concerned with this working on Windows (Windows 10).

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

Is there a clean way to fix files path issue whether the program is launched from console or Eclipse?

I'm currently working on a Java project in which I have to open files I stored in a data directory next to src.
When I launch my program from Eclipse, to access these files: I type "data/fileName" whereas when I use console I have to type "../data/fileName".
(I couldn't manage to execute java src/Main from project directory and got the error :
Error: Could not find or load main class src.Main.java
Caused by: java.lang.ClassNotFoundException: src.Main.java )
Is there a way to make my program runnable on both console and Eclipse?
To give some context: I usually intended to run only on Eclipse but I encountered issues launching nano from Eclipse ($TERM variable , redirecting pipes to dev/tty also) so console execution has become a requirement.
I can't change my Eclipse configuration since this project won't be run on my computer and if it doesn't run because of default Eclipse settings, well...
Thank you for your replies.
Cordially.
Yes. Don't put those files there. There are 2 broad categories:
Read-only data that is as much a part of your app as your class files are. Think 'list of US states for the 'state' dropdown', 'an icon png to be shown on my user interface', 'a file containing a bunch of SQL to be used to initialize an empty database', and more.
For this, the proper way to go is YourClass.class.getResourceAsStream("foo.txt"), which will give you an input stream for reading the file "foo.txt", which is in the same place "YourClass.class" is. Even if it is in a jar file, for example.
This does mean that as part of your build, these files need to be in the jar. eclipse's limited build system does this. If you level up as a programmer and use a build system (you should be levelling up here), put them in src/main/resources and the build system should take care of it.
Or, the second category: Files that the user is supposed to edit, or files that need to be modified by your app.
These don't go anywhere near your jar file; executable and user-editable stuff should be nowhere near each other. These should be in the user home dir, you can fetch it with System.getProperty("user.home").
Note that to run java stuff, 'src' shouldn't be part of the story at all, java can't run source files, only class files. Also, the argument isn't a dir, it's a class name. java -cp path/to/your/app.jar com.foo.pkg.YourClass is how you run java code, not java src/Main.

JAVA Properties file in Windows Virtual Store causing problems through updates [duplicate]

I try to make a setup with Inno Setup for my program.
I have installed more file XML in the same folder as the .exe. The install work well, but when I run the program and modify the XML, the file is saved in another place, not the folder of the .exe and I can't find it. I think the file is stored in the PC because the program can open it without problems.
I also try to make the same setup with InstallAware Express 7 and it works well. Io I think it's not a problem in my exe but in Inno Setup.
Thanks
I think you are a victim of Windows File virtualization.
You probably install data files to Program Files folder.
That folder is not writable (unless your program runs with elevated privileges). If your program does not have application manifest, Windows considers it a legacy application that is not aware of its inability to write to Program Files and enables file virtualization. So, when your application tries to write the data/XML files, Windows redirects the write (and future reads) to a virtual store (C:\Users\username\AppData\Local\VirtualStore). The actual files in the Program Files are not modified.
It's difficult to answer, why it works with the InstallAware Express. If you tried it after the Inno Setup, the results can be affected by an existence of the file in the virtual store.
Anyway, the root cause is that your application tries to write the files in the Program Files. That's just wrong. No application should write to Program Files.
See also Application does not work when installed with Inno Setup.

How to make a .plist for a mac applications

I'm trying to turn a java program into a mac .app file, or more accurately, a native mac application. This requires a .plist file (see here) but I can't seem to find anywhere that works in telling me how to make one. I set up the directories as they specified, and my application debugs properly. Its just every time I try to open the application, it immediately shuts down. Does anyone know how to make a (minimalist even, for now) working plist file?
Right click on your project and select Export. Assuming you on using a Mac, there will be an option to output an application bundle.
Once you have created the app bundle (which itself is just a directory), go here to find the Info.plist file:
MyApp.app/Contents/Info.plist
From there you can edit the plist, if you need to.

JAR executable doesn't start if it's in Programs directory

I'm into a very strange issue that's making me crazy .-.
I'm working on a relatively big Java project on Windows, using NetBeans and IzPack to prepare the graphical installation package.
Everything is ok, the compiled installer seems to work and my program is copied in 'C:\Programs\MyProject' folder.
But... when I double click on the myproject.jar in that folder it doesn't start at all. I obviously tried to open a prompt and type 'java -jar myproject.jar' but nothing, not even a line of error code.
The curious facts are two:
if I open it using the prompt with administration rights it works
in the same folder there is another jar, 'uninstaller.jar' created by izpack, and it works with double click.
I double checked my JVM installation, the PATH/JAVA_HOME/... values, and Properties->Security tab of my JAR but the permissions to execute/read/write for every kind of user are ok, and also are equal to the uninstaller.
So what's the problem? Thanks
This is almost certainly caused by Windows UAC on Vista and Windows 7.
Your program is probably trying to write to data files in the same directory as it is installed.
On Windows, well behaved programs write to the users or all users app data directory.
The location of that directory varies depending on the version of Windows.
You can use the system property "user.home" to find a safe place to store data.
You can also get a list of environment variables for shared and per user program data folders from here.

Categories