Odpowiedź jest prosta: jeśli uruchamiasz program uruchamiający z IDE, takiego jak Eclipse lub IntelliJ IDEA, prawdopodobnie nie ma on w pierwszej kolejności ustawionego System.console()
, więc nie ma nic, co mógłby z niego dziedziczyć subprocess. Po prostu spróbuj napisać coś do System.console()
z programu uruchamiającego, spowoduje to również niepowodzenie z tym samym błędem. Ale jeśli uruchomisz program uruchamiający z interaktywnej konsoli, takiej jak Cmd.exe lub Git Bash, zarówno program uruchamiający, jak i proces uruchomiony za pośrednictwem ProcessBuilder
, może napisać do System.console()
. Twój launcher nie potrzebuje nawet "cmd", "/c"
, działa z tymi parametrami lub bez nich.
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");
}
}
dziennika konsoli po uruchomieniu z IntelliJ IDEA:
dziennika
Exception in thread "main" java.lang.NullPointerException
at de.scrum_master.stackoverflow.Launcher.main(Launcher.java:11)
(...)
Console gdy zaczęło się od cmd.exe:
Hi, I am the launcher app!
Hi, I am an externally started app!
Zapraszam do zadawania pytań uzupełniających .
Aktualizacja: Jeśli nie masz nic przeciwko temu, że program zewnętrzny działa we własnym interaktywnej konsoli zamiast w konsoli IDE, można użyć polecenia systemu Windows start
do tego celu, a następnie albo cmd /c
(okna jest zamknięte natychmiast po zewnętrznego programu została zakończona) lub cmd /k
(okno pozostaje otwarte, aby sprawdzić wynik):
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();
}
}
Ale jeśli to chcesz odczyt/zapis z/do tej konsoli, jesteś z powrotem na placu # 1. Zapytałeś, dlaczego nie możesz dziedziczyć System.console()
do podprocesu. Cóż, to dlatego, że jest null
ze względu na sposób, w jaki Eclipse i IntelliJ uruchamiają programy Java z IDE (patrz [tutaj] dla informacji tła). Ale jak Magnus powiedział, nadal masz System.{out|in}
i można ich używać w następujący sposób:
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.
Nie jest to możliwe, czy to dobry pomysł, 'System.console()' jest dostępne tylko wtedy, gdy program jest uruchamiany w trybie interaktywnym, ponieważ rozmawiasz z inną aplikacją java, znacznie lepiej załadujesz ją jako bibliotekę. Alternatywnie możesz po prostu użyć 'System.in' i' System.out' zamiast 'Console', które będzie działać poza trybem interaktywnym. – Magnus
Możliwe dupe http://stackoverflow.com/q/22799265/6754053 –