如何只允许一个 .Jar 实例,并让它使用来自其他尝试实例的参数?

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

我有一个棘手的问题,我将首先勾勒出一个背景以使事情更容易理解。

背景

我在 Java 中制作了一个音频播放器,它可以使用命令行参数启动,也可以不使用。应用程序的 .jar(用 Netbeans 制作)被包装在一个 .exe 文件(用 Launch4j 制作)中,这样你就可以用 .exe 打开例如一个 mp3 文件,然后里面的 .jar 采用它的 String[] 中的文件路径参数。

这种方法(目前)的问题是,如果您一次 select 多个 mp3 文件并同时打开它们,它们都会在单独的 windows音频播放器。然而,我想要的是所有文件都在应用程序的一个实例中打开。

然后我尝试让 Launch4j 只允许 .jar/.exe 的一个实例,希望所有 selected 文件都可以在一个应用程序中打开,不幸的是,这并没有奏效。

我认为的解决方案

所以我希望能够在 windows 中 select 多个 .mp3 文件,并且它们的所有文件路径都作为命令行参数传递给应用程序的一个实例。或具有相同结果的不同方法。有谁知道在实际应用中如何实现?

非常感谢。我也会尝试继续寻找潜力 solutions/ideas。

--编辑--

主要方法已准备好接收多个文件。我已经实现了一段代码,将应用程序的所有命令行参数保存到一个 .txt 文件中,当我只允许一个带有 Launch4j .exe 文件的实例时,.txt 中似乎只有一个参数当我尝试打开多个 mp3 文件时文件。

如果我允许 .exe 有多个实例,那么我只需多次启动 .jar 应用程序(我尝试打开每个文件一次)。

我使用javaRMI(远程方法调用)制作了一个单实例应用.

RMI 尝试侦听具有用户定义端口号的套接字。

启动jar时

  • 如果没有人服务于该端口,那么这个实例就是 RMI 服务器。建立一个 GUI Window。使用 main 的 args 调用 open。
  • 如果已经有服务应用程序,则通过 RMI 发送带有主参数的打开。然后正常退出,return from main.

代码: 未经测试,因为您可能想以不同的方式安排事情。

public interface OpenRMI extends Remote {
    void open(String[] args) throws RemoteException;
}

public class SingleInstanceApp implements OpenRMI {

    private static final String RMI_ENTRY = "ImJustACowLolAudioPlayer";

    public static void main(String[] args) throws RemoteException,
            AccessException, NotBoundException {
        System.out.println("main " + Arrays.toString(args));
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        Registry registry = LocateRegistry.getRegistry();
        OpenRMI openRMI;
        try {
            System.out.println("bind with new OpenRMI");
            SingleInstanceApp app = new SingleInstanceApp();
            openRMI = (OpenRMI) UnicastRemoteObject.exportObject(app, 0);
            registry.bind(RMI_ENTRY, openRMI);
            System.out.println("Player bound");
            app.create(); // Server.
        } catch (AlreadyBoundException e2) {
            System.out.println("lookup as someone else bound before us");
            openRMI = (OpenRMI) registry.lookup(RMI_ENTRY); // Client.
        }
        openRMI.open(args);
    }

    private void create() {
        new Thread(true) { // Daemon thread, or start GUI
            @Override
            public void run() {
                System.out.println("create " + this);
                for (int i = 0;  i < 10; ++i) {
                    Thread.sleep(1000L);
                }
                shutdown();
            }
        }
    }

    private void shutdown() throws RemoteException,
            NotBoundException, AccessException {
        System.out.println("close " + this);
        Registry registry = LocateRegistry.getRegistry();
        registry.unbind(RMI_ENTRY);
    }

    @Override
    public void open(String[] args) throws RemoteException {
        System.out.println("open " + this + ": " + Arrays.toString(args));
    }
}

我希望有更体面的 类。

我修好了,经过几个小时的编程和中间的休息

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

以上是做什么的 上面的应用程序检查是否有其他参数文件,如果有,它将继续生成一个新名称,直到该名称可用为止。然后它将参数打印到该文件。打印参数后,它启动音频播放器。在音频播放器中发生以下情况:

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}
}}

以上是做什么的 它试图为自己申请一个服务器套接字。如果已经有一个,那么它不会继续启动应用程序。这样一次只有一个实例 运行 。 (在 PORT 处你只需填写一个随机整数)。

结合这两个,您可以读取第一个应用程序创建的文本文件并将它们解释为第二个应用程序中的参数。

那么它如何将它们解释为参数? 好吧,我已经在程序中固定了一个计时器,我告诉音频播放器在指定文件夹中查找第一个 arg 文件 (arg0.txt)。如果找到它,它会将它与所有 arg+i.txt 文件一起添加到数组列表中。

这可能不是最快的方法,但肯定很有效。