2017-02-04 3 views
8

mit System.Console habe ich ein zwei Programme:einen anderen Prozess starten verfügbar

  • erste, die Console Objektdaten lesen und schreiben verwendet
  • Sekunden, das mit einigen dynamisch berechneten Argumente sollten
  • laufen erste

zweiten Programmcode sieht wie folgt aus:

String[] arguments = { 
    "cmd", "/c", 
    "java", "-cp", classPath 
    lauchClass, 
    // Arguments for first program 
} 
ProcessBuilder pb = new ProcessBuilder(arguments); 
pb.environment().putAll(System.getenv()); 
pb.directory(workDir); 
pb.inheritIO(); 

Process process = pb.start(); 
process.waitFor(); 

Wenn Faust Programme st Kunst von Sekunde, System.console() ist null und es schlägt mit NPE fehl.

Also, Frage ist: Gibt es eine Möglichkeit, einen anderen Prozess mit System.console() verfügbar zu machen?

+3

Dies ist nicht wirklich möglich, oder eine gute Idee, die 'System.Console()' ist Nur verfügbar, wenn das Programm im interaktiven Modus ausgeführt wird. Da Sie mit einer anderen Java-App sprechen, ist es viel besser, sie als Bibliothek zu laden. Alternativ können Sie auch 'System.in' und' System verwenden.out 'anstelle von' Console', die außerhalb des interaktiven Modus funktioniert. – Magnus

+0

Mögliche Betrüger von http://Stackoverflow.com/q/22799265/6754053 –

Antwort

4

Die Antwort ist einfach: Wenn Sie Ihren Launcher von einer IDE wie Eclipse oder IntelliJ IDEA ausführen, hat er wahrscheinlich System.console() nicht gesetzt, also gibt es nichts, von dem der Subprozess erben kann. Versuchen Sie einfach, etwas aus dem Launcher in System.console() zu schreiben, es wird auch mit dem gleichen Fehler fehlschlagen. Wenn Sie jedoch Ihren Launcher über eine interaktive Konsole wie Cmd.exe oder Git Bash starten, können sowohl der Launcher als auch der über ProcessBuilder gestartete Prozess in System.console() schreiben. Ihr Launcher braucht nicht einmal "cmd", "/c", es funktioniert mit oder ohne diese Parameter.

package de.scrum_master.stackoverflow; 

import java.io.File; 
import java.io.IOException; 

public class Launcher { 
    public static void main(String[] args) throws IOException, InterruptedException { 
    String classPath = "out/production/SO_ExternalProcessSystemConsole"; 
    String launchClass = "de.scrum_master.stackoverflow.MyApp"; 
    File workDir = new File("."); 
    System.console().printf("Hi, I am the launcher app!%n"); 

    String[] arguments = new String[] { 
//  "cmd", "/c", 
     "java", "-cp", classPath, 
     launchClass 
    }; 
    ProcessBuilder pb = new ProcessBuilder(arguments); 
    pb.environment().putAll(System.getenv()); 
    pb.directory(workDir); 
    pb.inheritIO(); 

    Process process = pb.start(); 
    process.waitFor(); 
    } 
} 
package de.scrum_master.stackoverflow; 

public class MyApp { 
    public static void main(String[] args) { 
    System.console().printf("Hi, I am an externally started app!%n"); 
    } 
} 

Konsolenprotokoll, wenn von IntelliJ IDEA gestartet:

Exception in thread "main" java.lang.NullPointerException 
    at de.scrum_master.stackoverflow.Launcher.main(Launcher.java:11) 
    (...) 

Konsolenprotokoll beim Start von cmd.exe:

Hi, I am the launcher app! 
Hi, I am an externally started app! 

Fühlen Sie sich frei keine Follow-up-Fragen zu stellen .


Update: Wenn Sie nichts dagegen hat, dass das externe Programm läuft in einer eigenen interaktiven Konsole statt in der IDE-Konsole können Sie den Befehl von Windows verwenden start zu diesem Zweck und dann entweder cmd /c (Fenster ist geschlossen unmittelbar nach externes Programm beendet) oder cmd /k (Fenster bleibt offen für das Ergebnis zu überprüfen):

package de.scrum_master.stackoverflow; 

import java.io.File; 
import java.io.IOException; 

public class Launcher { 
    public static void main(String[] args) throws IOException, InterruptedException { 
    String classPath = "out/production/SO_ExternalProcessSystemConsole"; 
    String launchClass = "de.scrum_master.stackoverflow.MyApp"; 
    String[] arguments = new String[] { 
     "cmd", "/c", "start", 
     "cmd", "/k", "java", "-cp", classPath, launchClass 
    }; 
    ProcessBuilder pb = new ProcessBuilder(arguments); 
    Process process = pb.start(); 
    process.waitFor(); 
    } 
} 

Aber wenn dann möchten Sie zum lesen/schreiben von/auf dieser Konsole sind Sie wieder auf Platz # 1. Sie haben gefragt, warum Sie System.console() nicht an einen Subprozess erben können. Nun, das liegt daran, dass es null ist, weil Eclipse und IntelliJ Java-Programme aus der IDE starten (siehe [hier] für Hintergrundinformationen). Aber wie Magnus sagte, haben Sie noch System.{out|in} und kann sie wie folgt verwenden:

package de.scrum_master.stackoverflow; 

import java.io.File; 
import java.io.IOException; 
import java.util.Scanner; 

public class Launcher { 
    public static void main(String[] args) throws IOException, InterruptedException { 
    String classPath = "out/production/SO_ExternalProcessSystemConsole"; 
    String launchClass = "de.scrum_master.stackoverflow.MyApp"; 
    File workDir = new File("."); 
    System.out.println("Hi, I am the launcher app!"); 

    String[] arguments = new String[] { "cmd", "/c", "java", "-cp", classPath, launchClass }; 
    ProcessBuilder pb = new ProcessBuilder(arguments); 
    pb.environment().putAll(System.getenv()); 
    pb.directory(workDir); 
    pb.inheritIO(); 
    Process process = pb.start(); 
    process.waitFor(); 

    System.out.print("What is your favourite city? "); 
    Scanner scanner = new Scanner(System.in); 
    String city = scanner.nextLine(); 
    System.out.println("I guess that " + city + " is a nice place."); 
    } 
} 
package de.scrum_master.stackoverflow; 

import java.util.Scanner; 

public class MyApp { 
    public static void main(String[] args) { 
    System.out.println("----------------------------------------"); 
    System.out.println("Hi, I am an externally started app."); 
    System.out.print("Please enter your name: "); 
    Scanner scanner = new Scanner(System.in); 
    String name = scanner.nextLine(); 
    System.out.println("Hello " + name + "!"); 
    System.out.println("----------------------------------------"); 
    } 
} 
Hi, I am the launcher app! 
---------------------------------------- 
Hi, I am an externally started app. 
Please enter your name: Alexander 
Hello Alexander! 
---------------------------------------- 
What is your favourite city? Berlin 
I guess that Berlin is a nice place. 
+0

Wenn Sie nicht mit meiner Antwort zufrieden sind, können Sie bitte erklären, was Sie erwarten? – kriegaex

+0

Nur eine Frage. Du sagtest, so gibt es nichts, von dem der Subprozess erben kann. Aus dem Code: 'pb.environment(). PutAll (System.getenv())' und 'pb.inheritIO()'. Außerdem ist die ProcessImpl-Klasse "static synchronized native long create()" mit dem Parameter "stdHandles", der den Standard-IO-Handles entspricht (für Windows-Implementierung). Warum ist dies nicht genug für die JVM, um eine Konsoleninstanz zu erstellen? – Ivan

+1

Sehen Sie sich mein Update mit zwei weiteren Varianten an, die Sie je nach Anwendungsfall ausführen können. – kriegaex

Verwandte Themen