С использованием cmd в режиме ожидания в С++ или java

Я использую OpenSSL в своем приложении С++. Проблема в том, что я использую exec("Open ssl command") Затем он выполнит эту конкретную команду, но на самом деле эта команда репсонирует, я имею в виду, что она далее просит вас "Are you sure you want to do this Y/N?" Я не знаю, как удовлетворить этот сценарий. Как я могу использовать java или С++ для запуска командной строки, которая реагирует, Любая помощь будет оценена. Благодаря

Ответ 1

Прост в Java. Просто:

  • Получить Process дескриптор.
  • Прочитайте входной поток Процесс для приглашений, записанных на стандартный вывод.
  • Отвечайте на запросы, выполнив запись в поток Процесs > .

Вот быстрый Groovy образец, потому что он даже проще, чем Java:

def cmd = ... // the command you want to run
def process = cmd.execute()
def processStdout = new Scanner(process.inputStream)
def processStdin = process.outputStream
def outputLine = processStdout.nextLine()
if (outputLine == 'some prompt written to stdout') {
    processStdin << 'your response\n'
}

Если вы не можете следовать за Groovy, я могу развернуть его на Java.

Обратите внимание, что этот пример не обрабатывает потенциально важные задачи по обеспечению полного уничтожения stdout и stderr вложенного процесса, чтобы предотвратить блокировку, а также не позволяет гарантировать, что процесс завершается чисто.

Обновление: Здесь то же самое в Java:

import java.io.OutputStream;
import java.util.Scanner;

public class SubprocessIO {
    public static void main(String[] args) throws Exception {
        String[] cmd = { ... your command as a series of strings ... };
        Process process = Runtime.getRuntime().exec(cmd);
        Scanner processStdout = new Scanner(process.getInputStream());
        OutputStream processStdin = process.getOutputStream();
        String outputLine = processStdout.nextLine();
        if (outputLine.equals("some prompt written to stdout")) {
            processStdin.write("your response\n".getBytes());
            processStdin.flush();
        }
    }
}

Я забыл сделать заметку в первом раунде, что \n в ответе имеет решающее значение, предполагая, что приложение ожидает, что вы что-то введете, а затем нажмите Enter. Кроме того, вам, вероятно, лучше использовать системное свойство line.separator

Ответ 2

В основном вам просто нужно убедиться, что вы вводите всю необходимую информацию в командной строке и используйте -batch, чтобы избежать дополнительных вопросов, например:

openssl ca -days 3650 -out client.crt -in client.csr -config \path\to\configs -batch -passin pass:PASSWORD -key password

Если это не работает для какой-либо конкретной команды openssl, укажите в своем вопросе, какую команду вам нужно выполнить.

Ответ 3

Для openssl ответ Wimmel - правильный подход. В зависимости от вашего конкретного варианта использования вы можете подготовить или создать файл конфигурации, содержащий повторяющиеся параметры, и указать переменные параметры (и указатель на файл конфигурации) в командной строке. Параметр -batch, доступный, по крайней мере, с помощью общих команд openssl для управления сертификатами, гарантирует отсутствие интерактивности - если вы указали недостаточные параметры, команды будут терпеть неудачу.

Для запуска команды и оценки ее результатов вам по-прежнему нужна соответствующая функциональность. В Java вы используете классы ProcessBuilder и Process. В С++ нет стандартного способа сделать это (функция system() слишком ограничена для большинства применений), поэтому вам необходимо использовать C-специфичные для платформы функции (например, CreateProcess, posix_spawn или fork/exec) или найти подходящую библиотеку С++.

Но для прямого ответа на интерактивные вопросы программно эти интерфейсы могут быть недостаточными. Интерактивный диалог может быть довольно сложным. Обычно это не так просто, как обработка всех входных и выходных данных в виде простого символьного потока. Детали зависят от платформы и программы, но вам может понадобиться что-то вроде expect (см. http://en.wikipedia.org/wiki/Expect), чтобы справиться с этим.

Обновление: конечно, подход к вызову внешнего CLI для всего этого не обязательно является лучшим и вводит совершенно новый набор посторонних побочных проблем. Возможно, вам лучше использовать подходящий криптографический API (например, BouncyCastle http://www.bouncycastle.org/)