# Ausführen einer Batch mit Parameterübergabe funktioniert nicht richtig



## buggy84 (30. Okt 2014)

Hallo Java-Forum Gemeinde,

ich bin auf ein mehr oder weniger großes Problem gestoßen, ich hoffe eventuell kennt jemand eine Antwort. 

Ich möchte eine Batch aus meiner Java-Applikation starten. Der Batch muss ich einen Parameter übergeben, welchen, erschließt sich für euch:


```
Runtime.getRuntime().exec(new String[] { "cmd","/c","javafix.lnk",System.getProperty("java.home")} );
```

 Prinzipiell geht das auch, allederdings nur, wenn 
	
	
	
	





```
System.getProperty("java.home")
```
 einen Pfad ohne Leerzeichen liefert. Sobald der Pfad ein Leerzeichen enthält, geht das CMD-Fenster auf und sofort wíeder zu... schwer zu beschreiben, die Batch bricht sofort ab. 

Kennt jemand das Problem?
Für jede Hilfe und Anregung bin ich dankbar.


----------



## Androbin (30. Okt 2014)

Problem: Durch Leerzeichen getrennt gilt dein Parameter als zwei einzelne Parameter

==> Lösung: Der Parameter muss durch Anführungszeichen zusammengefasst werden

==> ==> Problem: Anführungszeichen markieren in Java für einen String

==> ==> ==> Lösung: Schreibe die Anführungszeichen (um den Parameter) mit Backslash: \"


----------



## buggy84 (30. Okt 2014)

Soweit klar. Der Ansatz funktioniert leider trotzdem nicht.
Alles in allem könnte mein Parameter ja auch als 2 (oder mehrere) Parameter gelten, die Batch sollte trotzdem funktionieren.


----------



## arilou (30. Okt 2014)

Ruf' erst mal diese "javafix.lnk" mit den Problemparametern direkt auf (ohne eigenes Java-Programm drumrum, ohne cmd.exe drumrum) in einer Ms-Dos-Eingabebox. Vielleicht ist ja "alles korrekt" am Aufruf, und das via .lnk gestartete Programm selbst endet eben unerwartet schnell?

Wenn das problemlos fuktioniert, kannst' anschließend mal (aus der Ms-Dos-Box) die
cmd /c
-Variante aufrufen, und austüfteln wie das genau funktioniert.

Erst danach würde ich anfangen, den Aufruf in Java durchführen zu wollen.

Außerdem bietet es sich an: Runtime.getRuntime().exec(...) liefert eine Process-Objekt zurück, dessen .getOutput und .getError -Streams solltest du aufnehmen und nachsehen, was darin ausgegeben wird.


----------



## buggy84 (30. Okt 2014)

Die Batch (Ziel der .lnk) arbeitet gut, ich habe das mehrfach mit verschiedenen Tests bewiesen. Hier ist alles ok.

Was das "austüftlen" mit cmd /c angeht, weiß ich nicht genau was du damit meinst. Was ich benutze ist die gängige Art und Weise. Oder bist du da anderer Meinung? Hast Du andere Vorschläge?

Das Process-Object und die angeboteten Streams werde ich prüfen, danke für den Hinweis.

edit:

Ergebnis:


```
ErrorStream java.io.FileInputStream@1c98360
OutputStream java.io.BufferedOutputStream@d03350
```


----------



## taro (30. Okt 2014)

Folgendes sollte es bei dir tun:


```
Runtime.getRuntime().exec(new String[] { "cmd","/c","javafix.lnk",System.getProperty("\"java.home\"")} );
```



> Alles in allem könnte mein Parameter ja auch als 2 (oder mehrere) Parameter gelten


Könnte zwar, sollte aber nicht - Funktionsweise überdenken!


----------



## buggy84 (30. Okt 2014)

taro hat gesagt.:


> Folgendes sollte es bei dir tun:
> 
> 
> ```
> ...




Das funktioniert nicht... Sollte aber klar sein. Ich habs trotzdem ausprobiert, das Ergebnis war das zu erwartende.




taro hat gesagt.:


> Könnte zwar, sollte aber nicht - Funktionsweise überdenken!


2x Konjunktiv = keine Aussage
Damit kann ich nichts anfangen, mehrere Beispiele im Netz belegen, dass es funktioniert, die ich in der Batch aber eben mehrere Parameter auszuwerten habe (je nach Anzahl der Leerzeichen...).


----------



## Thallius (30. Okt 2014)

Was passiert denn wenn du die property erst in einen String packst und dann diesen in das exec?


----------



## buggy84 (30. Okt 2014)

Hab ich auch schon versucht, ist leider dasselbe Ergebnis.


----------



## taro (30. Okt 2014)

sorry ... knapp daneben:


```
Runtime.getRuntime().exec(new String[] { "cmd","/c","javafix.lnk","\""+System.getProperty("java.home")+"\""} );
```

Jetzt aber

EDIT: Bitte daran denken, dass du den "Rest" des Pfades sowie den Namen der Datei direkt an den String hängen musst!

```
Runtime.getRuntime().exec(new String[] { "cmd","/c","javafix.lnk","\""+System.getProperty("java.home")+"\\rest\\des\\pfades\\batch.lnk\""} );
```


----------



## buggy84 (30. Okt 2014)

Hi taro,

danke für deine Mühe. Mit


```
System.getProperty("java.home")
```

bekomme ich das Installtionsverzeichnis von Java zurück. Mehr brauch ich nicht als Parameter. Wozu ist "der Rest des Pfades" gut? Was übersehe ich denn hier? Langsam verzweifle ich ein bisschen.


----------



## taro (30. Okt 2014)

Man nutzt exec eigentlich, um eine externe Datei auszuführen - die musst du aber auch angeben - nur ein Pfad (in deinem Falle das Java-Homeverzeichnis) reicht da nicht - woher soll das System wissen, dass du die Angabe mit einer Batch verarbeiten willst, wenn du diese nicht angibst.

Normalerweise müsste die Befehlszeile so aussehen:

cmd /c "<Pfad>\irgendetwasausführbares.bat" <irgendwelche_Parameter>

das vermisse ich aber bei dir.


----------



## buggy84 (30. Okt 2014)

Das ist nicht ganz korrekt. Eine Pfadangabe ist nur dann notwendig, wenn die auszuführende Datei in einem anderen Ordner als 
	
	
	
	





```
System.getProperty("user.dir")
```
 liegt. Das ist bei mir nicht der Fall, daher reicht 

```
"cmd","/c","javafix.lnk"
```
 aus. Meine Pfadangabe ist der Dateiname.


```
System.getProperty("java.home")
```
 ist der *Parameter*, den ich übergeben will...

Ganz im Übrigen führe ich eigentlich eine Verknüpfung aus. Die Verknüpfung zeigt auf die Batch.


----------



## arilou (30. Okt 2014)

Wenn alle Stricke reißen, schreib' doch das, was du ausführen willst, erst in eine Batchdatei, und start's dann:

```
void runIt() throws IOException
{
  BufferedWriter bw = new BufferedWriter( new FileWriter ( "mybatch.bat" ) );
  bw.write( "javafix.lnk \""+System.getProperty("java.home")+"\"" );
  bw.newline();
  bw.flush(); bw.close() ;
  Runtime.getRuntime().exec( "cmd" , "/c" , "mybatch.bat" );
}
```
Nicht schön, aber ein Problem weniger.


----------



## taro (30. Okt 2014)

Das ist doch auch keine Lösung.

Lass dir doch mal die Systemmeldung dazu ausgeben ... wie es geht, findest du hier: https://blog.art-of-coding.eu/executing-operating-system-commands-from-java/ (Input and Output)


----------



## Thallius (30. Okt 2014)

taro hat gesagt.:


> sorry ... knapp daneben:
> 
> 
> ```
> ...



Ja und da sind wir dann wieder bei dem Thema File.seperator.

Niemals und wirklich niemals Pfade selber mit \ oder / zusammen bauen.

Gruß

Claus


----------



## taro (30. Okt 2014)

@Thallius: Grundsätzlich hast du recht(!) - da jedoch eine Verknüpfung per lnk-Datei nur unter Windoof funktioniert ....


----------



## arilou (30. Okt 2014)

taro hat gesagt.:


> Das ist doch auch keine Lösung.
> 
> Lass dir doch mal die Systemmeldung dazu ausgeben ... wie es geht, findest du hier: https://blog.art-of-coding.eu/executing-operating-system-commands-from-java/ (Input and Output)



1. Es ist eine Lösung, die funktioniert. Nicht sehr schön, aber tut erst mal.
2. Dein Link erklärt _allgemein_, wie man .exec verwendet, aber auf das konkrete Problem des TO geht er in keinster Weise ein und ist somit _hier_ nicht wirklich hilfreich.

Noch dazu wird dort Unsinn gemacht, wie z.B. in stdout eines Unterprozesses _nach dessen Ende_ noch was hinzuzufügen ?!? Der einzig sinnvolle Schreibvorgang auf Datenströme eines Unterprozess' wäre, in dessen stdin etwas zu schreiben - aber nicht, nachdem man mit .waitFor() auf sein Ende gewartet hat.

Und stdout und stderr eines Unterprozesses sollte man _nebenläufig_ aus seinen Datenströmen pollen, da Java nur 64k puffert, und dann den Unterprozess schlafen legt, bis die Puffer geleert sind - und sei's bis Sankt Nimmerlein.
_Sowas_ kann man dem Hilfslink ebenfalls nicht entnehmen.


----------



## buggy84 (30. Okt 2014)

taro hat gesagt.:
			
		

> Lass dir doch mal die Systemmeldung dazu ausgeben ...



Das werde ich machen...



			
				Thallius hat gesagt.:
			
		

> Ja und da sind wir dann wieder bei dem Thema File.seperator.
> 
> Niemals und wirklich niemals Pfade selber mit \ oder / zusammen bauen.



Da stimme ich zu. Nur Ärger mit der Hardcodiererei.




			
				arilou hat gesagt.:
			
		

> Wenn alle Stricke reißen, schreib' doch das, was du ausführen willst, erst in eine Batchdatei, und start's dann



Wenn alle Stricke reißen, hast du selbstverständlich recht, wird ich es so (oder abgewandelt) lösen müssen. Das ist dann aber nur eine Behandlung der Symptome, keine wirkliche Lösung. Ich würde wirklich gern wissen was das Problem ist.

edit:

Ich hab mir den link von taro jetzt angeschaut. In Zukunft werde ich, bevor ich große Versprechungen mache 



			
				buggy84 hat gesagt.:
			
		

> Das werde ich machen...


 solche Links ansehen und dann entscheiden. Das ist, wegen Nutzlosigkeit, gestrichen. Bringt mich nicht wirklich weiter.

edit2: 



			
				buggy84 hat gesagt.:
			
		

> keine wirkliche Lösung


 revidiere  ich ebenfalls. Im Grunde ist es eine Lösung und damit 





			
				arilou hat gesagt.:
			
		

> ein Problem weniger


 Dennoch bin ich bestrebt den Fehler meines Ansatzes zu finden, nur so vermeide ich das nächste Mal wieder ewig frustriert zu sein. Ich kann nicht schlafen, wenn ich das nicht in den Griff kriege...


----------

