Update eines Programms - Beenden eines anderen Prozesses überwachen

Tharsonius

Bekanntes Mitglied
Hallo zusammen,

Ich habe ein Java Programm was als Standalone auf einem PC läuft (kein Applet, kein Browser). Das programm liegt als .jar vor und wird ganz normal ausgeführt.
Neben dem Programm liegen in verschiedenen Ordnern diverse Bilder und Bibliotheken, die ich für das Programm brauche und die ich zur Laufzeit bei Bedarf lade.

Außerdem habe ich eine Datenbank, mit der ich arbeite. In dieser Datenbank ist die aktuelle Versionsnummer hinterlegt, die das Programm auch abfragt. Passt diese nicht mehr mit der eigenen Version überein, so wird derzeit eine Meldung ausgegeben und das Programm beendet sich dann. Bisher muss ich das Programm dann manuell updaten. Dies ist aber aufgrund der mittlerweile anwachsenden Menge an PCs etwas arg unpraktisch geworden.

Daher möchte ich nun eine automatische Update Routine für dieses Programm erstellen. Dieses Update soll in der Lage sein einerseits die Bibliotheken und Bilder, als auch das Programm selber auszutauschen.

Dateien aus der Datenbank zu holen ist gar kein Problem, das klappt auch alles.


Ich habe mir das so überlegt:
1. Mein Programm startet und überprüft die Version, so wie bisher auch.
2. Wenn ein Update nötig ist, dann wird ein Updater gestartet. Dies soll ein zweites kleines Programm sein, was ich gerade schreibe. Das Programm beendet sich dann natürlich.
3. Der Updater zieht nun die Daten aus der Datanbank und legt diese dahin, wo sie hin sollen. Auszutauschende Bilder, Bibliotheken etc werden dabei ersetzt.
4. Nach dem Update startet der Updater wieder mein Programm.



Mein Problem ist nun, wie kann ich im Updater überwachen, dass mein Programm beendet ist?
Ich kann das Programm ja nur austauschen, wenn es nicht läuft, ansonsten erhalte ich ja keinen zugriff auf das .jar File. Da sperrt sich Windows.
Da der Updater auch in einem separaten Prozess läuft kann ich auch nicht wirklich davon ausgehen, dass er sich schon rechtzeitig beendet. Daher würde ich gerne den Prozess irgendwie überwachen. Irgendwie stehe ich da aber auf dem Schlauch. Hat jemand eine Idee?
 
Ich habe lokal keine Virtuelle Maschine installiert. Ich starte meine Anwendung mittels batch Datei, die VM liegt daneben.
Kann ich da Web Start überhaupt ausführen?

Desweiteren habe ich keinen Server Speicherplatz zur Verfügung sondern lediglich die Datenbank.

Fragt nicht wieso, unser Admin ist seltsam... Hab da schon wochenlange Diskussionen hinter mir...
 
Ich hab mir da gerade was anderes überlegt, werde das ganze wohl über einen Launcher machen, den ich vorweg starte, der dann das Update macht und anschließend das eigentliche Programm startet.

Wenn ich mittels Runtime.getRuntime.exec(...) mein Programm starte bekomme ich ja den Prozess zurück.
Weiß jemand, was passiert, wenn der Prozess sich beendet? Wird der dann zu null, so dass ich im Launcher ein while(prozess != null) schreiben kann, um auf das Ende zu warten?

Oder kann ich das ganze durch irgend einen Listener mitbekommen?

Ich muss im Launcher halt wissen wann das Update durch ist, damit ich dann das Programm selber starten kann...
 
Ich hab mir da gerade was anderes überlegt, werde das ganze wohl über einen Launcher machen, den ich vorweg starte, der dann das Update macht und anschließend das eigentliche Programm startet.

Wenn ich mittels Runtime.getRuntime.exec(...) mein Programm starte bekomme ich ja den Prozess zurück.
Weiß jemand, was passiert, wenn der Prozess sich beendet? Wird der dann zu null, so dass ich im Launcher ein while(prozess != null) schreiben kann, um auf das Ende zu warten?

Oder kann ich das ganze durch irgend einen Listener mitbekommen?

Ich muss im Launcher halt wissen wann das Update durch ist, damit ich dann das Programm selber starten kann...

Ja, das funktioniert... mit Einschränkungen. Du kannst natürlich die Ressourcen, die für dein Bootstrapping nötig sind (JRE und Launcher) nicht so einfach austauschen, da hast du wieder das Problem.

Tipp(auch wenn er schon mal kam): mach es mit Webstart!!!!
 
der ansatz mit launcher ist richtig ... aber warum willst du aus dem launcher herraus einen neuen prozess starten ? ...
so lange du im launcher nicht explizit das upzudatene jar lockst *z.b. durch n URLClassLoader* kannst du damit machen was du willst ...
packe also einfach die update-funktion in den launcher ... und lade die neuen daten runter BEVOR du das auszuführende über n URLClassLoader läds *und damit lockst* und dann die main startest ...
den schwachsinn mit einzelnen prozessen ist zu umständlich ...

*tipp : in java 7 kann man auf einen URLClassLoader auch close() anwenden um die gelockten jar's wieder freizugeben ...*

@FArt
auch wenn TO es schonmal gesagt hat : er hat kein JRE installiert ... womit WebStart nicht funktioniert
 
@FArt
auch wenn TO es schonmal gesagt hat : er hat kein JRE installiert ... womit WebStart nicht funktioniert

Aber das ist eine Anforderung, die man m.E. in Frage stellen sollte. Eine Runtime kann jeder installieren. In einem Unternehmen können das die Admins sogar automatisieren bzw. werden die Clients gerne aus einem Image installiert. Somit ist das oft kein Problem. Der Ablauf danach wäre konsistent, gegenüber dem Aufwand, den ich mit pure Java treiben muss, vor allem wenn ich die Runtime noch mit warten muss.

Der "Gut-Fall" ist relativ einfach. Aber geh mal konsistent mit Fehlern um... Schreibrechte auf der Platte (gerade unter Windows ist mal wieder eine Datei gesperrt, weil ein Explorer offen ist usw.). Da kriegt man graue Haare mit und das wird ein Wartungsdesaster, außer man regelt das grundsätzlich nicht selber sondern mit einer Installersoftware.
 
Aber das ist eine Anforderung, die man m.E. in Frage stellen sollte.

Das habe ich bereits alles hinter mir. Ich habe mit unserem Admin bereits tagelange Diskussionen geführt.
Er ist Millionenprozentig davon überzeugt, dass Java das ganze Netzwerk unsicher macht. Deswegen wird hier in der ganzen Firma definitiv niemals ein Java installiert.

Ich weiss er ist ein Idiot, ich hab mir den Mund fusselig geredet, aber solange ich ihm nicht einen wissenschaftlichen Beweis geben kann, weigert er sich. Ich habe schlichtweg keine Lust mehr mit dem Vollpfosten zu diskutieren. Also habe ich eine VM daneben gelegt und starte mein Programm mittels Batch Datei aus dem Ordner.

Weiterhin bekomme ich keinen Serverplatz zur Verfügung. Ich kann zwar ein gemeinsames Laufwerk nutzen was von überall zugänglich ist, das wird aber per Skript einmal die Woche geleert...

Ich habe schlichtweg einfach keine Lust auf noch mehr Diskussion. Daher habe ich mir hier was anderes gebastelt, was zumindest noch solange halten muss wie ich in der Firma bin.

Aus diesem Grund ist Web Start leider nicht möglich, auch wenn das vieles so einfach machen würde. *schnief*



Na ja, ich habe jetzt einen Launcher zusammen gestrickt, der folgendermaßen vor geht.
1. Programm starten. (Programm beendet mit exit code 1 wenn Update nötig ist, sonst mit 0)
2. Warten auf Prozessende... 0 = Launcher beenden, 1 Update starten
3. Update Starten, ist nen separates Programm, was ich geschrieben habe. Dieses schaufelt die Files aus der Datenbank auf die Platte.
4. Wenn Update beendet ist, Patcher starten. Dieser kopiert die Dateien an die korrekte Stelle.
5. Programm normal starten
6. Launcher beenden.


Warum verschiedene Prozesse:
Für den Datenbank Zugriff brauche ich eine Bibliothek. Diese kann ich nur tauschen, wenn auf diese nicht zugegriffen wird. Daher habe ich den Updater, der die Daten rüber schaufelt und den Patcher, der die dann austauscht. Ich könnte den Updater im Launcher unterbringen, das ist richtig, wollte das aber gerne getrennt haben.


Ach, hier noch mal ein Programmschnippsel aus dem Launcher, wie ich das starten der Programme und das Warten auf das Beenden der Prozesse gebaut habe.

Java:
		Process prozess = null;
		try
		{
			prozess = Runtime.getRuntime().exec("./vm/bin/javaw -jar ./bin/Programm.jar");
		}
		catch(IOException e)
		{
                        // Fehler ausgeben
			System.exit(0);
		}
		if(prozess == null)
		{
                        // Fehler ausgeben
			System.exit(0);
		}
		boolean wait;
		wait = true;
		int wert = 0;
		while(wait)
		{
			try
			{
				wert = prozess.exitValue();
				wait = false;
			}
			catch(IllegalThreadStateException e)
			{
				// Nichts tun
			}
		}
		if(wert == 1)
		{
                 //hier passiert das Update
                }
 

Zurück
Oben