# Prüfen ob ein Programm gestartet wurde



## babuschka (15. Okt 2010)

Hallo miteinander

Ich möchte gerne per Java (am liebsten ohne Hilfe von C++/Batch etc.) testen, ob ein Programm gestartet wurde. Das ganze soll plattformunabhängig geschrieben werden. Ist so etwas in reinem Java zu verwirklichen?

Vielen Dank für eure Hilfe

Greez


----------



## The_S (15. Okt 2010)

Bei einem bestimmten Programm: Unter Umständen
Bei jedem beliebigen Programm: Nein


----------



## babuschka (15. Okt 2010)

Ja, das Programm ist bestimmt (VPN Client). Der Prozessname ist also bekannt.


----------



## KrokoDiehl (15. Okt 2010)

Wenn du das Programm aus deiner Java-Anwendung heraus startest (z.B. über Runtime.exec()) dann kannst du das entsprechende Process-Objekt prüfen.

Bei einem beliebigen anderen Programm, wie _The_S_ schon sagte: Nein. 
Das "reinste" Java was mir dazu einfällt ist dass du einen Befehl vom Betriebssytem (z.B. "ps -ef" in Linux) ausführst, die Ausgabe liest und dann durchsuchst... ist aber weder wirklich plattformunabhängig noch performant.


----------



## babuschka (15. Okt 2010)

KrokoDiehl hat gesagt.:


> Wenn du das Programm aus deiner Java-Anwendung heraus startest (z.B. über Runtime.exec()) dann kannst du das entsprechende Process-Objekt prüfen.



Von dem habe ich schon gelesen. Ist aufgrund eurer Antworten wahrscheinlich die beste Lösung. 

Schade, trotzdem vielen Dank für eure schnelle Hilfe.


----------



## The_S (15. Okt 2010)

Du könntest auch untersuchen, ob VNC irgendwas bestimmtes macht, wenn es gestartet ist - bspw. ein Lock-File irgendwo ablegen, einen Port belegen, ... und dann das testen.


----------



## babuschka (15. Okt 2010)

Die Idee mit dem Port finde ich sehr interessant. Ohne danach zu suchen, frage ich kurz hier nach wie ich so etwas testen kann?


----------



## The_S (15. Okt 2010)

Zuerst musst du rausfinden, OB VNC beim Start einen Port belegt. Fall es das tut, kannst du in deinem Programm selbst versuchen, den Port zu reservieren. Klappt das, kannst du davon ausgehen, dass VNC nicht läuft. Klappt es nicht, läuft VNC (oder ein anderes Programm, das sich den Port geschnappt hat). Evtl. schickt VNC auch eine bestimmte Nachricht bzw. ermöglicht eine Kommunikation über den Port. So könntest du dich zu den Port verbinden und sicher testen, ob VNC läuft oder nicht. Könnte klappen, daVNC ja auf Remote-Verbindungen wartet.


----------



## babuschka (15. Okt 2010)

Gehe ich richtig in der Annahme, das ich dies mit Sockets versuchen muss?


----------



## The_S (15. Okt 2010)

Naja, versuchen ist recht sinnlos. Du solltest vielmehr in Erfahrung bringen (Recherche, Supportanfragen, Bedienungsanleitung, ...), ob VNC so etwas anbietet oder sogar eine API bereitstellt.


----------



## babuschka (18. Okt 2010)

Hallo

Leider erstellt das VPN Programm keine Temp-Files noch gibt es eine API dazu. Dafür weiss ich, mit welchen Parametern das Programm eine Verbindung aufbaut. (Host, Port)
Mit diesen Information wollte ich nun eine SocketVerbindung via Java aufbauen, um zu prüfen, ob das Programm schon verbunden ist. (BindException => Verbindung steht bereits)

Dies wurde wie folgt geschrieben:

```
public static String checkVPN() {
      try {
          InetAddress host = InetAddress.getByName("xxx.xxx.xxx.xxx");
          int port = xxx; 
          
          Socket socketVpn = new Socket(host, port);
          socketVpn.close();
      } catch (BindException  portBusy){
          return portBusy.toString();
      } catch (IOException  e){
          return e.toString();
      }
      return "VPN-Client wurde nicht gestartet";  
  }
```

Soweit so gut, leider funktioniert dies noch nicht wie gewünscht. Wenn ich jedoch in der Konsole mit "netstat -ano" die aktiven Verbindungen anzeigen lasse, ist die VPN Verbindung klar ersichtlich und mit "HERGESTELLT" gekennzeichnet. 

Ich weiss nun leider nicht wo der Fehler liegen könnte. 

Vielen Dank für eure HIlfe


----------



## The_S (19. Okt 2010)

Eigentlich solltest du doch nur den Port brauchen. Läuft ja lokal bei dir, also localhost als host ... oder missverstehe ich dich gerade?


----------



## Gast2 (19. Okt 2010)

Du solltest anstatt dem Socket ein ServerSocket erstellen.
Der ServerSocket ist dafür zuständig auf einem bestimmten Port zu lauschen und Verbindungsanfragen entgegen zu nehmen.
Der Socket übernimmt die eigentliche Kommunikation zwischen zwei Endpunkten.

Wenn du in deinem Programm dann versuchst mit nem ServerSocket auf dem VPN Port zu lauschen sollte dir eine Exception um die Ohren fliegen.


----------



## The_S (19. Okt 2010)

Jo, stimmt. So wie du es vorhast, solltest du auch einen ServerSocket verwenden.


----------



## babuschka (19. Okt 2010)

Leider tretten keine Exceptions auf, obwohl der Port unter netstat klar ersichtlich ist. Die einzige Änderung die ich gemacht habe ist die, dass ich den Socket in ServerSocket umbenannt habe. Bin mir ehrlich gesagt auch nicht ganz im Klaren, warum ich auf dem Port lauschen soll, anstatt ihn zu belegen mit einem "normalen" Socket. Wahrscheinlich verstehe ich noch etwas falsch. 

Vielen Dank für eure Hilfe


----------



## The_S (19. Okt 2010)

Mit einem Socket verbindest du dich zu einem Port, könntest also mit dem Programm, das an dem Port lauscht, kommunizieren. Mit einem ServerSocket lauschst du selbst an einen Port.


----------



## babuschka (19. Okt 2010)

The_S hat gesagt.:


> Mit einem Socket verbindest du dich zu einem Port, könntest also mit dem Programm, das an dem Port lauscht, kommunizieren. Mit einem ServerSocket lauschst du selbst an einen Port.


In diesem Falle habe ich alles korrekt verstanden. 

Ich glaube jedoch das Problem liegt woanders. Ich führe mein Programm lokal auf einem Notebook aus. (wo auch der VPN-Client gestartet wird). Der Server, auf den ich connecte, liegt jedoch irgendwo anders im Internet. Wenn ich nun lokal auf dem Notebook auf dem Port 12345 lausche, tritt niemals eine Exception auf. Wenn ich jedoch einen Lokalen Port (wird unter netstat -ano bei den Lokalen Adressen angezeigt, in der Zeile der Remoteadresse die mir bekannt ist) angebe, tritt die genannte BindException auf. 
Ich bin mir nun immer noch nicht sicher, ob ich nicht den Remoteport mit einem Socket belegen muss, anstatt auf nach ihn zu lauschen. 

Ich hoffe ich konnte das mehr oder weniger verständlich erklären.


----------



## The_S (19. Okt 2010)

Achso, du möchtest dich von deinem Rechner auf einen anderen Rechner verbinden. Das geht so natürlich nicht. Der Client lokal muss irgendeinen Port belegen um diese Methode zu testen.


----------



## babuschka (19. Okt 2010)

Gut dann haben wir uns also verstanden.

Würde dies dann nicht funktionieren, wenn ich mit einem Socket eine Verbindung über den bekannten Port zur bekannten Adresse aufbaue. Sollte dann nicht eine Exception auftreten, wenn eine solche Verbindung (die vom VPN Programm) schon steht?


----------



## The_S (19. Okt 2010)

Hier zum Selbsttesten  :


```
ServerSocket ss = new ServerSocket(5555);
		Socket s1 = new Socket("localhost", 5555);
		Socket s2 = new Socket("localhost", 5555);
		ss.accept();
		ss.accept();
		System.out.println(s2.isConnected() + "/" + s1.isConnected());
```

Außerdem heißt es ja nicht, dass VNC immer sofort nach dem Start eine Verbindung aufbaut.


----------



## babuschka (19. Okt 2010)

Danke werde ich gleich testen und hier Rückmeldung geben. Und nochmals vielen Dank für deine grossartige Hilfe!



The_S hat gesagt.:


> Hier zum Selbsttesten  :
> Außerdem heißt es ja nicht, dass VNC immer sofort nach dem Start eine Verbindung aufbaut.


Das ist in meinem Falle auch egal. Es soll nur testen ob die Verbindung steht und ansonsten einen Hinweis ausgeben, dass man die Verbindung aufbauen soll.


----------



## The_S (19. Okt 2010)

Das ist jetzt aber schon ein komischer Use-Case ... naja, du machst das schon  .


----------



## ARadauer (19. Okt 2010)

Das hab ich mal wo gebraucht.... vielleicht hilft es dir... is halt auf windows beschränkt... 

```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TimerTask;


public class ProzessFinder extends TimerTask{
   
   public static void main(String[] args) throws IOException {
      ProzessFinder f =new ProzessFinder();
      f.run();
      
   }

   
   private static ArrayList<String> getLinesFromCmd(String c) throws IOException{
      ArrayList<String> lines = new ArrayList<String>();
      String cmd = "cmd /c "+c;
      Process p = Runtime.getRuntime().exec(cmd);

      InputStream is =  p.getInputStream();
      BufferedReader b = new BufferedReader(new InputStreamReader(is));
      String line = null;
      while((line = b.readLine())!= null){
         lines.add(line);         
      }
      return lines;
   }
   
   HashMap<Integer, Prozess> prozesse = new HashMap<Integer, Prozess>();

   
   public Prozess getProzessByPort(int port){
      synchronized (this) {
         return prozesse.get(port);
      }      
   }

   
   
   public void run() {
      long t = System.currentTimeMillis();

      HashMap<Integer, Prozess> tempProzesse = new HashMap<Integer, Prozess>();
      Prozess aktP = null;

      ArrayList<String> lines = null;
      try {
         lines = getLinesFromCmd("netstat -b");
      } catch (IOException e1) {
         return;
      }
      for(String line: lines){
         line = line.trim();
         if(line.length()==0) //nix
            continue;
         if(line.startsWith("[") && aktP != null){
            aktP.setName(line.substring(1, line.length()-1));
            tempProzesse.put(aktP.getPort(), aktP);
            aktP=null;
         }else {
            ArrayList<String> parts = getParts(line);
            if(parts.size()!=5)
               continue;
            int portNum = -1;
            try {
               String port = parts.get(1).split(":")[1];
               portNum = Integer.parseInt(port);
            } catch (Exception e) {
               continue;
            }
            aktP = new Prozess();
            aktP.setPort(portNum);
         }

      }
      synchronized (this) {
         prozesse = tempProzesse;
         //zu debug zwecken
         for(Integer port : prozesse.keySet()){
            System.out.println(port+" "+prozesse.get(port).getName());
         }
      }    
   
   }
   
   


   /**
    * Führt ein Commando auf der shell aus und liefert das Ergbenis als
    * ArrayList<String> zurück
    * @param c
    * @return
    * @throws IOException
    */
   


   /**
    * erstellt aus einer Zeile mit space getrennten Spalten fester Größe
    * eine ArrayList
    * @param line
    * @return
    */
   private static ArrayList<String> getParts(String line){
      ArrayList<String>  result = new ArrayList<String>();
      StringBuilder b = null;
      for(char c : line.toCharArray()){
         if(c!=' '){
            if(b==null){
               b = new StringBuilder(); 
            }
            b.append(c);
         }else{
            if(b!=null){
               result.add(b.toString());
               b=null;
            }
         }
      }

      if(b!=null)
         result.add(b.toString());

      return result;


   }


}
```


```
public class Prozess {
   String name;
   int port;
   
   
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public int getPort() {
      return port;
   }
   public void setPort(int port) {
      this.port = port;
   }

   public String toString(){
      return name+"-"+port;
   }


}
```


----------



## babuschka (19. Okt 2010)

Danke für den Code. Das Programm sollte jedoch plattformunabhängig laufen. Deshalb weiche ich auch auf die eher spezielle Port überprüfung aus.

+++++++++++UPDATE++++++++++++++++
Möchte hier noch erwähnen das ich mein Problem auf eine andere Weise lösen konnte. Ich werde diese Lösung hier nicht posten, da sie nur in meinem kleinen Spezialfall funktioniert und somit überflüssig wäre.

Trotzdem nochmals Danke an alle die hier geholfen haben.


----------

