Search code examples
javacommand-line-argumentsexewrappersingle-instance

How To Allow Only One .Jar Instance, And To Let It Use Args From Other Attempted Instances?


I've got a tough question, for which I will first sketch a background to make things more understandable.

Background

I have made an audioplayer in Java which can be launched with command line args, and also without. The application's .jar (made with Netbeans) is wrapped in a .exe file (made with Launch4j) so that you can open for example a mp3 file with the .exe, and then the .jar inside adopts the filepath in it's String[] args.

The problem with this approach (for now) is that if you select multiple mp3 files at once and you open them at the same time, they all get opened in seperate windows of the audioplayer. What I want however, is that all the files get opened in one single instance of the application.

What I then attempted is to let Launch4j allow only one instance of the .jar/.exe in the hopes that all the selected files would be opened in one application, this did unfortinately not work.

What I see as a solution

So I want to be able to select multiple .mp3 files in windows, and that all their filepaths get passed on as a command line arg to one single instance of the application. Or a different approach that has the same result. Does anyone know how to realize this in the actual application?

Many thanks in advance. I will try to keep looking for potential solutions/ideas as well.

--Edits--

The main method is ready to receive multiple files. I have implemented a piece of code that saves all the command line args of the application to a .txt file, and when I allow only one single instance with the Launch4j .exe file, there only appears to be one single argument in the .txt file when I try to open multiple mp3 files.

If I allow the .exe to have multiple instances, then I simply have the .jar application being launched multiple times (one time for each file I try to open).


Solution

  • I fixed it, after some hours of programming and taking breaks inbetween

    package argsbuilder;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    
    public class ArgsBuilder
    {
    
    public static void main(String[] args)
    {
        checkIfRunning(args);
    }
    
    private static void checkIfRunning(String[] args)
    {
        buildFile(args);
    
        ProcessBuilder pb = new ProcessBuilder("core.exe"); //core.exe is a .exe wrapper with the  .jar audioplayer in it
        try
        {
            Process p = pb.start();
        }catch (IOException f){System.out.println(f);}
    }
    
    private static void buildFile(String[] args)
    {
        try
        {
            boolean notdone = true;
            int i=0;
            File f;
            while(notdone)
            {
                f = new File("arg" + i + ".txt");
                 if(f.exists())
                 { 
                     i++;
                 }
                 else
                 {
                    PrintStream out = new PrintStream(new FileOutputStream(new File("Folder Location" + "arg" + i + ".txt")));
                    System.setOut(out);
                    System.out.println(args[0]);
                    notdone = false;
                 }
            }
        }catch(Exception g){System.out.println(g);}
    }}
    

    What the above does The above application checks if there are other argument files, and if there are it will keep generating a new name untill the name is free. It then prints the argument to that file. After it has printed the argument, it launches the audioplayer. In the audioplayer the following happens:

    import javafx.embed.swing.JFXPanel;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    
    public class YourApp {
    
    public static void main(String[] args) 
    {
        try
        {
        socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
    
    
        //Everything you need to launch the application in the try
        }catch(Exception g){//Nothing in the catch}
    }}
    

    What the above does It tries to claim a serversocket for itself. If there already is one then it does not proceed to launch the application. That way only one instance will be running at a time. (at PORT you just fill in a random integer).

    Combining those 2, you can read the textfiles created by the first application and interpret them as arguments in the second application.

    So how does it interpret them as arguments? Well, I already had a timer fixed into the program, and I tell the audioplayer to look for the very first arg file (arg0.txt) in a specified folder. If it finds it it adds it to an arraylist, along with all arg+i.txt files.

    It might not be the fastest way, but it surely works well.