# Nur eine laufende Applikation erlauben?



## manuel k (2. Okt 2007)

Hallo!


Ich möchte überprüfen ob meine Java Applikation auf dem Server bereits läuft. Ist dies der Fall soll ein weiteres Ausführen des Programms nicht möglich sein.

Der Hintergrund ist der, dass das Programm per Windows Autostart ausgeführt wird, und ich diverse Remotedesktop zugänge habe. Jedesmal wenn nun ein anderer Remotedesktop Benutzer angemeldet wird, so startet auch das Programm ein 2tes mal.

Ich habe bereits bei manchen Java to .exe Tools die Option "Nur eine laufende Instanz erlauben" gesehen. Allerdings möchte ich den selben Effekt mit .jar Dateien erreichen.



Thx 4 help!


manuel k.


----------



## tuxedo (2. Okt 2007)

Mit ein wenig suchen im Forum hättest du die eine oder andere Lösungsstrategie gefunden.

Die Idee die ich ganz schick fand war, einen Dummy-Socketserver zusammen mit der Anwendung zu starten. Direkt vor dem Programmstarte und vor öffnen des Socketservers wir deinfach gecheckt ob dieser Port schon von einem anderen Socketserver belegt wurde.

Wenn die Anwendung zum ersten mal gestartet wird, ist der Port (hoffentlich) nicht belegt und der Socketserver kann starten.

Startet man die Anwendung ein zweites mal, wird festgestellt dass der Port schon belegt ist. Folglich muss bereits eine Instanz des Programms laufen. 

Nachteil: Du müsstest sicher gehen dass der Port des Dummy Socket-Servers von keiner anderen Anwendung die auf dem PC installiert ist genutzt wird.


Weitere Details bietet dir die Suchfunktion.

- Alex


----------



## manuel k (2. Okt 2007)

Ja die Idee funktioniert grundsätzlich, aber dieser Fall ist nicht mein Ziel.

Es ist ja grundsätzlich möglich im System nachzufragen ob ein Programm schon läuft oder nicht.. zumindest mit c-Programmen.

Somit wollte ich wissen ob dies auch in Java auf diese Art und Weise möglich ist.
Die Lösung über einen Socket Server ist ja grundsätzlich nur ein Provisorium.

Ich habe ja schon halb Google nach Lösungen durchsucht, aber nur eine brauchbare Lösung (allerdings für ein C-Programm) gefunden, und mittlerweile gehen mir die Such-Schlagwörter aus...


----------



## tuxedo (2. Okt 2007)

Du willst also "allgemein" wissen welches Java-Programm gerade läuft?

Hmm... Ich weiß momentan nur, dass Java, wenn alles richtig eingestellt ist (was bei 2pc's nicht der fall war), in einem Verzeichnis namens "hsperfdata_<Rechnerloginname>" die PIDs gespeichert werden. Mittels JConsole oder einer JMS-Anwendung kannst du da drauf zugreifen. Musst du mal im Netz googeln.

Ach ja: Das hsperfdata_<Rechnerloginname> Verzeichnis liegt im TMP Verzeichnis das via Umgebungsvariable definiert ist.

- Alex


----------



## tuxedo (2. Okt 2007)

manuel k hat gesagt.:
			
		

> Ja die Idee funktioniert grundsätzlich, aber dieser Fall ist nicht mein Ziel.



ich darf dich doch nochmal zitieren?



> Ich möchte überprüfen ob meine Java Applikation auf dem Server bereits läuft. Ist dies der Fall soll ein weiteres Ausführen des Programms nicht möglich sein.
> 
> ...
> 
> Ich habe bereits bei manchen Java to .exe Tools die Option "Nur eine laufende Instanz erlauben" gesehen. Allerdings möchte ich den selben Effekt mit .jar Dateien erreichen.



Na dann ist doch die Socketserver-Lösung eine praktikable und einfache Alternative, oder etwa nicht? Mit JMS wird das ganze glaub ich wesentlich aufwendiger und komplexer. 

Von Java aus das Betriebssystem fragen "Läuft gerade eine Java Anwendungs namens XYZ" geht IMHO nicht. Wenn, dann musst du, wie bereits erwähntm Java, oder besser die eigene Anwendung (via Socket) selbst fragen.
Oder deine Anwendung erstellt selbst eine PID File im User-Home... Wege gibts genug. 

- Alex


----------



## Guest (2. Okt 2007)

alex0801 hat gesagt.:
			
		

> Hmm... Ich weiß momentan nur, dass Java, wenn alles richtig eingestellt ist (was bei 2pc's nicht der fall war), in einem Verzeichnis namens "hsperfdata_<Rechnerloginname>" die PIDs gespeichert werden. Mittels JConsole oder einer JMS-Anwendung kannst du da drauf zugreifen.
> 
> - Alex



Das ist schon mal sehr Interessant!
Java bietet also offensichtlich keine vordefinierten Methoden die beim start eines Programms überprüfen, ob dieses bereits läuft.

Ich denke ich hab jetzt eine Idee wie ich das Ganze recht simpl realisieren kann.
Werde das ganze dann Posten wenn ich was brauchbares Programmiert habe.


Schönen Dank für die Lösungsvorschläge!


----------



## Guest (3. Okt 2007)

OK habe jetzt eine relativ einfache und gut funktionierende Lösung gefunden:
Dabei wird beim ersten Programmstart eine Datei unter beliebigem Pfad erstellt, und bei Programmende (auch im Falle eines Programmabbruchs durch eine Exception) wieder gelöscht.
Existiert diese Datei beim Programmstart, wird dies durch eine bool'sche Variable angezeigt, und es steht dem Benutzer frei, sein Programm nun beim Start zu beenden, oder zumindest eine Warnung anzuzeigen.

Hier ser Source:


```
package exec;

import java.io.File;
import java.io.IOException;

public class CheckRunningInstance {
	
	private String path;
	private String prefix = "sysID";
	private String suffix = ".prf";
	private boolean isSingleInstance = false;
	
	File AppIdentifier;
	
	public CheckRunningInstance(String path, String prefix, String suffix){
		this.path = path;
		this.prefix = prefix;
		this.suffix = suffix;
	}
		
	public boolean isSiungleInstance()
	{
		return this.isSingleInstance;
	}
	public void findIdentFile()
	{
		AppIdentifier = new File(path+"/"+prefix+suffix);
		
		try {
			if(!AppIdentifier.createNewFile()){
				System.out.println("Program already started");
				isSingleInstance = true;

			}
			else{
				AppIdentifier.deleteOnExit();
			}
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}
	}
}
```



_L-ectron-X hat diesen Beitrag am 01.11.2007 um 12:21 editiert._
_Code-Tags eingefügt._


----------



## tuxedo (3. Okt 2007)

Anonymous hat gesagt.:
			
		

> OK habe jetzt eine relativ einfache und gut funktionierende Lösung gefunden:
> }



Naja, ich glaube ich hatte dich ja auch drauf hingewiesen:



			
				alex0801 hat gesagt.:
			
		

> ...
> Oder deine Anwendung erstellt selbst eine PID File im User-Home... Wege gibts genug.


----------



## L-ectron-X (3. Okt 2007)

Wenn deine Kiste abschmiert, wird nichts mehr gelöscht und dein Programm wird bei einem Neustart des Systems demzufolge auch nicht mehr gestartet...
Also keine so gute Idee. Hättest du dir mal die Mühe gemacht, das Forum zu durchsuchen, wärst du auch auf dieses Problem gestoßen, denn das wurde ausführlich diskutiert.

Hier gibts jede Menge bereits besprochene Möglichkeiten mit Quellcode-Beispielen: http://www.java-forum.org/de/viewtopic.php?t=55421


----------



## tuxedo (3. Okt 2007)

BTW: Unter Linux läufts genauso... Wenn mir ein Dienst abschmiert und die PID File nicht gelöscht wird kann sein dass ich vor dme nächsten Start des Programm diese File erst löschen muss.

Aber okay, Linux ist auch ein bisschen ne andere Welt. Würde sich aber in Windows mit einer einfachen Abfrage "Sicher dass keine weitere Instanz läuft?" lösen lassen. Kommt halt auf den Anwendungsfall drauf an, soll heißen: "Wie idiotensicher mus die Anwendung sein?!"

Ohne jetzt das Forum nach der anderen Diskussion abgesucht zu haben: Der Weg über die JVM eigene PID ist vielleicht etwas "sicherer". Sollte AFAIK auch mit nem Systemcrash zurecht kommen.

- Alex

[update]

Vielleicht ist auch das hier hilfreich:
http://java.sun.com/javase/6/docs/technotes/tools/share/jps.html
http://www.galileocomputing.de/open...26_005.htm#mj88051fab899ff9a6b0c4d01570a3ff51


----------



## L-ectron-X (3. Okt 2007)

alex0801 hat gesagt.:
			
		

> Würde sich aber in Windows mit einer einfachen Abfrage "Sicher dass keine weitere Instanz läuft?"


Das ist ein Hebel an der falschen Stelle...
Warum sollte man damit das Konzept wieder aufweichen?


----------



## tuxedo (3. Okt 2007)

Ich sag ja: Kommt auf den Anwendungsbereich an... Ist sicherlich nicht überall die "brauchbare" oder "beste" Lösung ...


----------



## thE_29 (4. Okt 2007)

Es gibt diese Callback zeugs unter Windows!

http://jeans.studentenweb.org/java/trayicon/trayicon.html#download

Dieses TrayIcon bietet diese Möglichkeiten!

Hab das so gemacht


```
String appName = "MeinAppName";
     long result = WindowsTrayIcon.sendWindowsMessage(appName, 1234);
     if (result != -1)
     {
         // If window exists, there's already an instance of our app running
         // Print message and exit (other app will restore its window when receiving
         // our message - see WindowsMessageCallback
         System.out.println("[Already running other instance of " + appName +
                            " (returns: " + result + ")].");
         return false;
     }
else
{
     // Init the Tray Icon library given the name for the hidden window
     WindowsTrayIcon.initTrayIcon(appName );
     WindowsTrayIcon.setWindowsMessageCallback(new WindowsMessageCallback());
}
```

Dann die Klasse WindowsMessageCallback


```
public class WindowsMessageCallback implements TrayIconCallback
{
   public int callback(int param)
   {
       // Param contains the integer value send with sendWindowsMessage(appName,param)
       System.out.println("[Other instance started (parameter: "+param+")].");
       // Return integer value to other process
       return 4321;
   }
}
```

Wahrscheinlich gibts das ganze auch in einer Lib ohne TrayIcon, aber ich weiß es halt das es so auch geht!

Aber um Plattformunabhängig zu bleiben (wenn das gewünscht ist) würde ich die Port Variante empfehlen! Also mit udp lauschen


----------

