[JAVA] ProcessBuilder

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Ik wil graag vanuit java at runtime een executable aanroepen, daarvoor heb ik de volgende code geschreven:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static String execute(String directory, List<String> cmd) {
   StringBuilder output = new StringBuilder();
   try {
      ProcessBuilder builder = new ProcessBuilder(cmd);
      Map<String, String> environ = builder.environment();
      builder.directory(new File(directory));
      final Process p = builder.start();
      BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
      String line;
      while ((line = input.readLine()) != null) {
         output.append(line+"\n");
      }
      input.close();
   } catch (IOException e) {
      e.printStackTrace();
   }
   return output.toString();
}


Wanneer ik deze code aanroep als volgt:

Java:
1
2
3
4
5
6
List<String> command = new ArrayList<String>();
command.add("cmd");
command.add("/c");
command.add("java");
String result = execute("C:\\",command);
System.out.print(result);


Dan krijg ik keurig netjes de output te zien, echter wil ik graag de output voor 'java -version'. Helaas lukt het me niet om dit voor elkaar te krijgen, simpelweg '-version' aan de lijst command toevoegen werkt niet. Tevens werkt het niet om de listitem 'java' te vervangen door 'java -version' of bijv. '\"java -version\"'.

Ik heb al een hoop gezocht op het internet, zonder resultaat, vandaar dat ik hier jullie hulp vraag.

Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 17-09 16:09

NetForce1

(inspiratie == 0) -> true

-version aan de command-list toevoegen zou toch wel moeten werken, krijg je daar een foutmelding uit?

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Wil je de versie weten van Java, dan kan je misschien beter dit proberen: System.GetProperty("java.version");

http://www.roseindia.net/...le/java-get-version.shtml

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • kim72
  • Registratie: Oktober 2001
  • Laatst online: 28-03 14:55
Komt die versie output misschien in de error output terecht?
p.getErrorStream() zo uit mijn hoofd...

Acties:
  • 0 Henk 'm!

  • terje7601
  • Registratie: September 2009
  • Laatst online: 08-02-2024
kim72 schreef op woensdag 21 april 2010 @ 08:45:
Komt die versie output misschien in de error output terecht?
p.getErrorStream() zo uit mijn hoofd...
Dit is inderdaad het probleem. Als je gewoon alle output wil teruggeven op dezelfde stream, kun je ook

Java:
1
builder.redirectErrorStream(true);


gebruiken.

Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Snake schreef op woensdag 21 april 2010 @ 08:37:
Wil je de versie weten van Java, dan kan je misschien beter dit proberen: System.GetProperty("java.version");

http://www.roseindia.net/...le/java-get-version.shtml
offtopic:
Hoewel dit advies klopt, is RoseIndia in het algemeen GEEN goede site om tips/voorbeelden vandaan te halen. Zelfs in dit simpele geval staat er nog een behoorlijke fout in hun voorbeeld-code (twee keer "os.version" in plaats van "java.version").

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • bredend
  • Registratie: September 2001
  • Laatst online: 21:45
Dit zou wel moeten werken dan. Alle opties moeten apart in een array; geen spaties in de commando's.
Java:
1
2
3
4
5
6
7
List<String> command = new ArrayList<String>();
command.add("cmd");
command.add("/c");
command.add("java");
command.add("-version");
String result = execute("C:\\",command);
System.out.print(result);

Acties:
  • 0 Henk 'm!

  • terje7601
  • Registratie: September 2009
  • Laatst online: 08-02-2024
bredend schreef op woensdag 21 april 2010 @ 12:10:
Alle opties moeten apart in een array; geen spaties in de commando's.
Niet waar, want ook

Java:
1
2
3
4
5
List<String> command = new ArrayList<String>();
command.add("cmd");
command.add("/c java -version");
String result = execute("C:\\",command);
System.out.print(result);


werkt correct.

Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Of je doet het gewoon zonder cmd /c; dat is over het algemeen niet nodig om een process op te starten (sterker nog: vaak is het een bron van problemen.

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
NetForce1 schreef op woensdag 21 april 2010 @ 08:28:
-version aan de command-list toevoegen zou toch wel moeten werken, krijg je daar een foutmelding uit?
Nee, het geeft gewoon geen output.
Snake schreef op woensdag 21 april 2010 @ 08:37:
Wil je de versie weten van Java, dan kan je misschien beter dit proberen: System.GetProperty("java.version");

http://www.roseindia.net/...le/java-get-version.shtml
Natuurlijk wil ik niet de versie van java weten, maar is dit slechts een simpel voorbeeld van een executable aanroepen met een argument.
terje7601 schreef op woensdag 21 april 2010 @ 11:45:
[...]

Dit is inderdaad het probleem. Als je gewoon alle output wil teruggeven op dezelfde stream, kun je ook

Java:
1
builder.redirectErrorStream(true);


gebruiken.
Inderdaad, waarom als ik vragen mag? En is dit wel een nette oplossing of is er een nettere oplossing?

@bredend & terje7601
Dit werkt niet, zoals ik ook al aangegeven heb in de TS, toch bedankt voor het meedenken.

@Remus
Zonder de '/c' blijft het cmd process actief, waarop de java code dus blijft hangen. En helemaal zonder 'cmd /c' lijkt idd hetzelfde effect te hebben als met 'cmd /c'. Kortom dan heb ik hetzelfde probleem, namelijk dat het naar de error stream wordt geschreven.

Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Het waarom: Sun heeft blijkbaar besloten om de output van dit soort informatieve dingen naar de erroroutput te schrijven (bijvoorbeeld indien je -showversion gebruikt). In dat geval kan het vervelend zijn als het naar de standaardoutput gaat.

Met redirectErrorStream worden de normale en de error samengevoegd; of dat handig is ligt eraan wat je wil doen met de output. In dit specifieke geval zou je ook juist de errorstream kunnen uitlezen ipv de outputstream.

Het gebruik van cmd /c zorgt ervoor dat je een cmd window krijgt. Dat is vaak niet wat je wil, en daarna kan je daarmee vaak niet alle streams uitlezen (en de standaard input wordt volgens mij niet doorgelusd). Over het algemeen dus gewoon niet doen.

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Wat ik dus niet goed begrijp is het volgende:

Wanneer wordt iets naar de standaard output stream geschreven en wanneer wordt iets naar de error output stream geschreven?

Wanneer ik 'java' aanroep, wordt dit naar de standaard output stream geschreven, terwijl 'java -version' naar de error output stream geschreven wordt. Waar wordt dit verschil gemaakt, in 'java.exe' of ergens in de jvm die mijn code uitvoert? Dus is het 'java.exe' die naar de standaard output stream stuurt, maar merk je dit normaal gesproken niet op omdat een console beide streams toont?

Acties:
  • 0 Henk 'm!

  • terje7601
  • Registratie: September 2009
  • Laatst online: 08-02-2024
Memorice schreef op woensdag 21 april 2010 @ 16:41:
@bredend & terje7601
Dit werkt niet, zoals ik ook al aangegeven heb in de TS, toch bedankt voor het meedenken.
In die 2de post wilde ik gewoon bredend's statement weerleggen. Wat ik wilde zeggen:

Niet waar, want ook [...] werkt correct na het oplossen van het probleem in de TS, namelijk iets doen met de error stream.

Ik dacht dat dat wel duidelijk was uit de opeenvolging van posts, aangezien clutjespelberg het al gesuggereerd had als het probleem & ik in de post erna had bevestigd dat hij gelijk had. ;)
Memorice schreef op woensdag 21 april 2010 @ 16:41:
[...]

En is dit wel een nette oplossing of is er een nettere oplossing?
Zoals Remus zegt: het hangt ervan af waarin je geïnteresseerd bent. Misschien kun je eerst iets maken dat de outputstream van je process doorgeeft aan System.out & de errorstream van je process doorgeeft aan System.err Zo kun je duidelijk het onderscheid zien (een deftige IDE zal deze streams in verschillende kleuren weergeven) tussen wat het process allemaal teruggeeft & via welke stream. Daaruit kun je dan opmaken waarin je geïnteresseerd bent & of je het onderscheid tussen output & error-output wil maken.
Memorice schreef op woensdag 21 april 2010 @ 21:16:
Wat ik dus niet goed begrijp is het volgende:

Wanneer wordt iets naar de standaard output stream geschreven en wanneer wordt iets naar de error output stream geschreven?

Wanneer ik 'java' aanroep, wordt dit naar de standaard output stream geschreven, terwijl 'java -version' naar de error output stream geschreven wordt. Waar wordt dit verschil gemaakt, in 'java.exe' of ergens in de jvm die mijn code uitvoert? Dus is het 'java.exe' die naar de standaard output stream stuurt, maar merk je dit normaal gesproken niet op omdat een console beide streams toont?
Dat bepaalt java.exe & kun je niet weten zonder het gewoon te testen (bijv. door alles door te geven aan System.out & System.err) Inderdaad: in de console merk je het normaal gesproken niet, maar je kunt ook in een console bijv. enkel de error stream redirecten naar een log file (zie hier bijv.)

Acties:
  • 0 Henk 'm!

  • Memorice
  • Registratie: Maart 2006
  • Laatst online: 14-09 02:37
Ok, heel erg bedankt allemaal ik weet voldoende :)

Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Memorice schreef op woensdag 21 april 2010 @ 21:16:
Wat ik dus niet goed begrijp is het volgende:

Wanneer wordt iets naar de standaard output stream geschreven en wanneer wordt iets naar de error output stream geschreven?

Wanneer ik 'java' aanroep, wordt dit naar de standaard output stream geschreven, terwijl 'java -version' naar de error output stream geschreven wordt. Waar wordt dit verschil gemaakt, in 'java.exe' of ergens in de jvm die mijn code uitvoert? Dus is het 'java.exe' die naar de standaard output stream stuurt, maar merk je dit normaal gesproken niet op omdat een console beide streams toont?
Ik ziet net dat ik een deel van wat ik wilde typen niet daadwerkelijk getypt heb. De reden dat java de versie informatie naar error output stuurt is omdat bijvoorbeeld -showversion de versie afdrukt (waarschijnlijk via de zelfde weg als -version) en daarna het programma gewoon opstart. Afhankelijk van wat je programma doet is het heel erg vervelend als die versie informatie dan in de standaard output terechtkomt.

Daarnaast wordt het waarschijnlijk naar de error output gestuurd omdat het niet informatie is van een programma dat binnen de jvm uitgevoerd wordt ('normaal' verwacht gedrag bij het uitvoeren jvm), maar juist uitzonderlijke informatie is (namelijk informatie over de jvm zelf).
Pagina: 1