# Batchdatei ausführen und Ergebnisse abfragen



## cyliax (30. Mrz 2009)

So bevor ihr mich erschlagt, von wegen Suche benutzen usw. Hab ich gemacht und im Prinzip weiß ich auch wie es laufen müßte, nur irgendwas habe ich noch nicht hinreichend berücksichtigt. Also ich will aus meinem Programm heraus ne Batch-Datei starten, die intern widerum ne Batch-Datei startet über ein Call-Befehl (daran kann ich leider nichts ändern). Wie dem auch sei, ich bekomme es nicht hin, meine Anwendung für die Zeit der Batch-Ausführung (dauert ca. 20 Sek.) schlafen zu legen, damit sie auf das Ergebnis wartet. Des weiteren möchte ich gerne auswerten ob das ganze erfolgreich war oder nicht (anhand der Ausgaben).

Also diesen Code hab ich gerade, aber bis auf die erfolgreiche Ausführung klappt nichts anderes. Kein Block der Hauptanwendung und keine Rückgabewerte im String (line), obwohl bei normalem Aufruf der Batch was zu sehen ist. Ich danke euch schon jetzt für eure Hilfe.


```
String cmd = "cmd /c start test.bat datei.xml";

try {
	Process p = Runtime.getRuntime().exec(cmd);
	System.out.println("waiting for termination");
	try {
		p.waitFor();
	} catch (InterruptedException e) {}

	BufferedReader procout = new BufferedReader(
		new InputStreamReader(p.getInputStream())
	);
	String line;
	while ((line = procout.readLine()) != null) {
		System.out.println("  OUT> " + line);
	}
} catch( IOException e) {
	System.out.println("Fehler");
}
```


----------



## thE_29 (30. Mrz 2009)

cmd /c startet neuen Prozess und das Output ist somit nicht mehr greifbar für getInputstream!

Also du könntest das hier sagen:


```
String cmd = "cmd /c start test.bat datei.xml > C:\ausgabe.txt"
```
Danach ausgabe.txt auslesen!
Wobei ich sogar glaube, dass start kannst du dir sparen! cmd /c test.bat datei.xml > C:\asugabe.txt sollte reichen!

Am besten eine Datei mit java.io.File.createTempFile("blubor",".bat"); generieren lassen und das dann löschen...


----------



## cyliax (31. Mrz 2009)

hmm, ok, dann lassen wir das mal mit der ausgabe... aber es muss doch irgendwie festzustellen sein, ob die batch-datei fertig abgearbeitet ist oder nicht?

das "start" öffnet übrigens das konsolenfenster des betriebssystem, so dass man sehen kann, was er macht, ohne "start" arbeitet er die batch unsichtbar ab.


----------



## thE_29 (31. Mrz 2009)

Du könntest einfach die Batch starten 
Dann sollte er dann fertig sein, wenn die Batch durch ist!


----------



## cyliax (31. Mrz 2009)

ja ich starte auch die batch, aber mein java-programm läuft munter weiter und wartet nicht auf die vorgänge die da in der batch so passieren. das ganze dauert so 20 sekunden, dann schließt sich das schwarze fenster (bei benutzung von "start") wieder und genau das soll mein java-programm mitbekommen um dann mit ner anderen geschichte weiter zu machen.

Irgendwelche Ideen dazu?


----------



## cyliax (1. Apr 2009)

So, ihr seht ich lasse nicht locker... weil ich einfach denke es sich nicht um ein unlösbares Problem handelt.

Diesmal erst der Code der TestAnwendung.


```
import java.io.IOException;

public class ThreadTest {

	final Object syncObject = new Object();
	
	public ThreadTest() {
		init();
	}
	
	public void init() {
		Batch1 batch1 = new Batch1();
		batch1.start();

		Batch2 batch2 = new Batch2();
		batch2.start();
	}
	
	class Batch1 extends Thread {
	    	public void run() {
	    		ProcessBuilder pb = new ProcessBuilder( "cmd", "/c", "start", "test1.bat" );
	    		pb.redirectErrorStream( true );
			Process p = null;

			try{
       				synchronized (syncObject) {syncObject.wait();}
		        } catch (InterruptedException e) {}

                	try {
				p = pb.start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	}
	}
	
	class Batch2 extends Thread {
    		public void run() {
    			ProcessBuilder pb = new ProcessBuilder( "cmd", "/c", "start", "test2.bat" );
    			pb.redirectErrorStream( true );
			Process p = null;
			
    			try {
				p = pb.start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			synchronized (syncObject) {syncObject.notify();}
	    	}
	}

}
```

Was mir im Prinzip immer noch fehlt ist die Abfrage ob Batch 2 fertig abgelaufen ist um dann Batch 1 zu starten. Bis jetzt wird also das syncObject.notify in jedem Fall ausgeführt und so habe ich sofort zwei Konsolenfenster offen. Ich bitte immer noch um Hilfe. Danke.

PS: Man könnte ja auch meinen, dass p.waitFor() irgendwie weiterhilft, aber die Funktion liefert immer 0, egal ob Prozess p noch läuft oder nicht.


----------



## Ebenius (1. Apr 2009)

Jetzt hast Du das waitFor vergessen.

Man sollte die Ströme des Prozesses auf jeden Fall auslesen, sonst hängt Dir das Batch-File, wenn es zu viele Ausgaben macht.

Hier ist ein ausführbares Beispiel das [was auch immer] per "cmd /C" startet, die Ströme des Prozesses auf stdout und stdin piped und wartet, bis der Prozess beendet ist. Damit kannst Du sicher etwas anfangen: [HIGHLIGHT="Java"]public class BatchFileStarter {

  static class OutputPipe implements Runnable {

    private final Reader in;
    private final PrintStream out;

    /** Creates a new {@code OutputPipe}. */
    OutputPipe(Reader in, PrintStream out) {
      this.in = in;
      this.out = out;
    }

    public void run() {
      try {
        int c;
        while ((c = in.read()) != -1) {
          out.print((char) c);
        }
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
  }

  public static void main(String[] args)
        throws IOException, InterruptedException {
    if (args.length < 1) {
      System.err.println("Syntax: BatchFileStarter command [command [...]]");
      System.exit(1);
    }

    // command chain
    final String[] command = new String[2 + args.length];
    command[0] = "cmd";
    command[1] = "/C";
    System.arraycopy(args, 0, command, 2, args.length);

    // process creation
    final ProcessBuilder procBuilder = new ProcessBuilder(command);
    final Process process = procBuilder.start();
    createOutputPipe(process.getInputStream(), System.out);
    createOutputPipe(process.getErrorStream(), System.err);

    // wait for process to terminate and exit with process' return code
    System.exit(process.waitFor());
  }

  private static void createOutputPipe(InputStream in, PrintStream out) {
    new Thread(new OutputPipe(new InputStreamReader(in), out)).start();
  }
}[/HIGHLIGHT]
Ebenius


----------



## cyliax (1. Apr 2009)

ok, ich habe auch noch was entdeckt, womit mein problem zu tun haben könnte. es liegt glaube ich an diesem komischen "start", welches das fenster sichtbar macht. schalte ich das ab, bekomme ich auch die ausgaben der batch-datei in die eclipse-konsole und kann auch überprüfen ob das skript abgearbeitet ist... ich fummel mal weiter, glaube ich bin auf dem richtigen weg, melde mich dann nochmal.


----------



## Ebenius (1. Apr 2009)

cyliax hat gesagt.:


> ok, ich habe auch noch was entdeckt, womit mein problem zu tun haben könnte. es liegt glaube ich an diesem komischen "start", welches das fenster sichtbar macht. schalte ich das ab, bekomme ich auch die ausgaben der batch-datei in die eclipse-konsole und kann auch überprüfen ob das skript abgearbeitet ist... ich fummel mal weiter, glaube ich bin auf dem richtigen weg, melde mich dann nochmal.


Es liegt definitiv am _start_, das wollte ich eigentlich noch erwähnen und hab's vergessen. Aber trotzdem wichtig: Die Ströme auslesen. Der Fehler wird leider ständig begangen.

Ebenius


----------

