2017-02-04 2 views
8

У меня есть две программы:Запустить другой процесс с System.Console доступной

  • Первое, что использует объект консоли для чтения и записи данных
  • второй, который должен работать сначала с некоторыми динамически вычисляемых аргументов

Второй программный код выглядит следующим образом:

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(); 

когда кулак программ ЗТ arts from second, System.console() имеет значение null, и он не работает с NPE.

Итак, вопрос: есть ли способ запустить другой процесс с помощью System.console()?

+3

Это на самом деле не представляется возможным или хорошая идея, 'System.Console()' является доступен только в том случае, если программа запускается в интерактивном режиме, так как вы разговариваете с другим приложением Java, вам будет намного лучше загружать его в качестве библиотеки. В качестве альтернативы вы можете просто использовать 'System.in' и' System.out' вместо 'Console', который будет работать вне интерактивного режима. – Magnus

+0

Возможный обман http://stackoverflow.com/q/22799265/6754053 –

ответ

4

Ответ прост: если вы запускаете свою пусковую установку из среды IDE, такой как Eclipse или IntelliJ IDEA, возможно, у нее не установлено System.console(), поэтому нет ничего, что может наследовать подпроцесс. Просто попробуйте написать что-то System.console() из пусковой установки, он также потерпит неудачу с той же ошибкой. Но если вы запускаете свою пусковую установку с интерактивной консоли, такой как Cmd.exe или Git Bash, обе пусковая установка и процесс, запущенные через ProcessBuilder, могут записываться в System.console(). Ваша пусковая установка даже не нужна "cmd", "/c", она работает с этими параметрами или без них.

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"); 
    } 
} 

журнала консоли при запуске из IntelliJ IDEA:

журнала
Exception in thread "main" java.lang.NullPointerException 
    at de.scrum_master.stackoverflow.Launcher.main(Launcher.java:11) 
    (...) 

консоли при запуске из cmd.exe:

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

Не стесняйтесь задавать любые дополнительные вопросы ,


Update: Если вы не возражаете, что внешняя программа работает в своей собственной интерактивной консоли, а не в консоли IDE, вы можете использовать команду для Windows start для этой цели, а затем либо cmd /c (окна является закрыто сразу после внешней программы закончилась) или cmd /k (окно остается открытым для вас, чтобы проверить результат):

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(); 
    } 
} 

Но если затем вы хотите для чтения/записи из/в эту консоль, вы вернулись на площадь # 1. Вы спросили, почему вы не можете наследовать System.console() подпроцессу. Ну, это потому, что это null из-за того, как Eclipse и IntelliJ запускают Java-программы из среды IDE (см. [Здесь] для получения дополнительной информации). Но, как сказал Magnus, вы до сих пор System.{out|in} и их можно использовать следующим образом:

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

Если вас не устраивает мой ответ, можете ли вы объяснить, что вы ожидаете? – kriegaex

+0

Только один вопрос. Вы сказали: «Таким образом, ничто не может наследовать подпроцесс». Из кода: 'pb.environment(). PutAll (System.getenv())' и 'pb.inheritIO()'. Кроме того, класс ProcessImpl использует 'static synchronized native long create()' с параметром 'stdHandles', которые соответствуют стандартным ручкам ввода-вывода (для реализации Windows). Почему этого недостаточно, чтобы JVM создавал экземпляр консоли? – Ivan

+1

Посмотрите мое обновление с еще двумя вариантами того, что вы можете сделать, в зависимости от вашего варианта использования. – kriegaex

Смежные вопросы