2016-09-18 2 views
7

У меня есть эта простая программа Java:`System.Console()` `возвращает null`, если выполнены из` Gradle run`

package me.fornever.javaterminal; 
public class Main { 
    public static void main(String[] args) { 
     System.out.println("Console: " + System.console()); 
    } 
} 

И этот простой build.gradle:

apply plugin: 'java' 
apply plugin: 'application' 
mainClassName = 'me.fornever.javaterminal.Main' 

Когда я м его выполнения с помощью gradle --no-daemon run, я получаю следующий результат:

Console: null 

Если я исполню ее из терминала через gradle jar; java -cp '.\build\libs\java-terminal.jar' me.fornever.javaterminal.Main, я получаю следующее:

Console: [email protected] 

Я знаю, что System.console() может вернуться null, когда родительский процесс использует стандартный вывод перенаправления. Есть ли опция Gradle, чтобы отключить перенаправление и сделать консоль полностью доступной для моей программы?

Я разрабатываю библиотеку терминалов для Java, поэтому я хочу запускать свои тесты и исполняемые файлы без вмешательства Gradle в stdin/stdout/stderr.

Обратите внимание, что System.console() является null - это не единственная проблема, но наиболее очевидная проблема. На самом деле я хочу получить доступ к функции WinAPI WriteConsoleW из программы, выполненной gradle run, и я не могу использовать эту функцию по тем же причинам System.console(), являющийся null. Поэтому мне нужно отключить перенаправление вывода в Gradle, если эта опция доступна.

Также обратите внимание, что вопрос отличается от Gradle build null console object потому, что вопрос спрашивает, как использовать System.console() внутри скрипта Gradle, а не в программе Java, вызываемой gradle run; Я считаю, что они работают по-другому в этом вопросе, потому что ни один из ответов не работает или не применим к моему делу.

+0

Как вы можете * проверить * программу, использующую 'console()'? Вы не можете отправить тестовый ввод, и вы не можете проверить вывод, так что вы тестируете? – Andreas

+0

@ Аndreas в первую очередь я проверяю, работает ли он вообще и не бросает никаких исключений. И второй вариант - использовать какой-то зависящий от платформы API, такой как win32 'ReadConsoleOutput' или обертка, такая как' winpty'. Я пишу библиотеку обертки для консоли Windows, поэтому вполне можно использовать зависящие от платформы решения. – ForNeVeR

+0

Итак, когда вы делали веб-поиск, что вы нашли? Вы нашли этот дублирующий вопрос? – Andreas

ответ

1

Для того чтобы java.io.Console был доступен, дочерние процессы stdin и stdout должны указывать на терминал Linux/macOS/Unix или консоль Windows. Самый простой способ организовать это - наследовать stdin и stdout из родительского процесса, который уже настроен таким образом. Однако существует известное ограничение Gradle (GRADLE-3292), что тип задачи JavaExec не поддерживает, чтобы дочерний процесс наследовал потоки ввода-вывода родительского процесса.

Если тип задачи Gradle JavaExec был расширен для поддержки наследования stdin/stdout, то это можно сделать для работы gradle --no-daemon run.

Получение его для работы с демоном Gradle было бы намного сложнее и, вероятно, включало бы специфичный для платформы код для манипулирования псевдотерминалами или вызова консольного API Windows.

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