2016-05-06 17 views
1

Ich habe eine schwierige Frage, für die ich zuerst einen Hintergrund skizzieren werde, um die Dinge verständlicher zu machen.Wie kann man nur eine .Jar-Instanz zulassen und Args von anderen versuchten Instanzen verwenden?

Hintergrund

Ich habe einen Audioplayer in Java gemacht, die mit Befehlszeile args gestartet werden können, und auch ohne. Die .jar-Datei der Anwendung (mit Netbeans erstellt) wird in eine EXE-Datei (mit Launch4j) gepackt, sodass Sie beispielsweise eine MP3-Datei mit der EXE-Datei öffnen können. Anschließend übernimmt die .jar-Datei den Dateipfad in der Zeichenfolge []. Argumente.

Das Problem mit diesem Ansatz (für jetzt) ​​ist, dass, wenn Sie mehrere MP3-Dateien auf einmal auswählen und gleichzeitig öffnen, sie alle in separaten Fenstern des Audiowalkman geöffnet werden. Was ich jedoch will, ist, dass alle Dateien in einer einzigen Instanz der Anwendung geöffnet werden.

Was ich dann versucht habe, ist, Launch4j erlauben nur eine Instanz der. JAR /. EXE in der Hoffnung, dass alle ausgewählten Dateien in einer Anwendung geöffnet werden würde, hat dies leider nicht funktioniert.

Was ich sehe, als eine Lösung

Deshalb möchte ich in der Lage sein, mehrere MP3-Dateien in Windows zu wählen, und dass alle Dateipfade bekommen als Befehlszeilen arg zu einer einzigen Instanz des weitergegeben Anwendung. Oder ein anderer Ansatz, der das gleiche Ergebnis hat. Kann jemand das in der tatsächlichen Anwendung verwirklichen?

Vielen Dank im Voraus. Ich werde versuchen, weiterhin nach möglichen Lösungen/Ideen zu suchen.

- Edits -

Die wichtigste Methode ist bereit, mehrere Dateien zu empfangen. Ich habe einen Codeabschnitt implementiert, der alle Befehlszeilenargumente der Anwendung in einer TXT-Datei speichert, und wenn ich nur eine einzelne Instanz mit der Launch4j-EXE-Datei zulasse, scheint nur ein einzelnes Argument in der TXT zu sein Datei, wenn ich versuche, mehrere MP3-Dateien zu öffnen.

Wenn ich zulassen, dass die .exe mehrere Instanzen haben, dann habe ich einfach die .jar-Anwendung mehrmals gestartet (einmal für jede Datei, die ich öffnen möchte).

+0

Ist Ihre 'main'-Methode bereit, mehrere Dateipfade als Argumente zu erhalten? – Berger

+0

@Berger Ja, main ist bereit, mehrere Dateipfade als Argumente zu erhalten. Ich habe eine Testdatei erstellt, um zu sehen, was die Argumente sind, und jedes Mal wird nur ein Dateipfad als Argument angezeigt. – ImJustACowLol

+0

Verwenden Sie einen Socket ... – MadProgrammer

Antwort

1

ich es fest, nach einigen Stunden der Programmierung und Pausen dazwischen

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

Was die oben tut die obigen Prüfungen Anwendung, wenn es andere Argument Dateien vorhanden sind, und wenn es sie sind, werden sich erzeuge einen neuen Namen, bis der Name frei ist. Es druckt dann das Argument zu dieser Datei. Nachdem das Argument ausgedruckt wurde, wird der Audioplayer gestartet. In der Audioplayer geschieht folgendes:

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

Was die oben tut Es wird versucht, einen Serversocket für sich zu beanspruchen. Wenn bereits eins vorhanden ist, wird die Anwendung nicht gestartet. Auf diese Weise wird immer nur eine Instanz ausgeführt. (Bei PORT füllen Sie einfach eine zufällige Ganzzahl aus).

Kombinieren Sie diese 2, können Sie die Textdateien von der ersten Anwendung erstellt lesen und sie als Argumente in der zweiten Anwendung interpretieren.

Also, wie interpretiert es sie als Argumente? Nun, ich hatte bereits einen Timer in das Programm behoben, und ich sage dem Audiowiederzieher, um die allererste Arg-Datei (arg0.txt) in einem angegebenen Ordner zu suchen. Wenn es gefunden wird, fügt es es zusammen mit allen arg + i.txt-Dateien zu einer Arraylist hinzu.

Es ist vielleicht nicht der schnellste Weg, aber es funktioniert sicherlich gut.

2

I verwendet Java RMI (Remote Method Invokation) eine Einzelinstanz-Anwendung zu machen.

Eine RMI versucht, einen Socket mit einer benutzerdefinierten Portnummer abzurufen.

Beim Start des Glases.

  • Wenn niemand dient, dass Port, dann diese Instanz der RMI-Server ist. Richten Sie ein GUI-Fenster ein. Rufen Sie eine Öffnung mit den Argumenten des Hauptanrufs auf.
  • Wenn es bereits eine Serving-Anwendung gibt, senden Sie per RMI ein Open mit den Args des Main. Dann normal beenden, zurück von der Hauptstelle.

Code: Ungeprüfte wie Sie wahrscheinlich die Dinge anders anordnen möchten.

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

Ich würde etwas mehr anständige Klassen erwarten.

+0

Ich werde versuchen, das zu implementieren. Ich lasse Sie wissen, wenn es funktioniert :) – ImJustACowLol

+0

Könnten Sie auch Beispielcode zeigen, wie Sie das implementiert haben? All die Dinge in diesem Thema gehören zu einem Bereich, in dem ich völlig neu bin. – ImJustACowLol