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.
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
Mögliche Betrüger von http://Stackoverflow.com/q/22799265/6754053 –