Выполните несколько команд через консольное приложение C#

Я новичок в С# (и разработке в целом). Мне нужно написать метод на C#, который будет выполняться через консоль: - установить Ньюман; - казнить почтальона Беги.

Я создал метод, как показано ниже (я пробовал 2 варианта: ReadToEnd и WaitForExit), но, похоже, он застрял на каждом из этих шагов.

Любая помощь, как сделать так, чтобы обе команды выполнялись последовательно (1-я должна завершиться до 2-го запуска) и выйти после полного выполнения 2-й команды?

Заранее спасибо.

    public string Runner ()
    {
        string readOutput = null;
        var psiNpm = new ProcessStartInfo
        {
            FileName = "cmd",
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false
        };
        var pNpmRun = Process.Start(psiNpm);
        pNpmRun.StandardInput.WriteLine($"npm install -g newman");
        pNpmRun.WaitForExit();
        //pNpmRun.StandardOutput.ReadToEnd();
        pNpmRun.StandardInput.WriteLine($"newman run " +
            $"\"C:\\Postman\\Test.postman.json\" " +
            $"--folder \"TestSearch\" " +
            $"--environment \"C:\\Postman\\postman_environment.json\" " +
            $"--disable-unicode");
        pNpmRun.StandardOutput.ReadToEnd();
        pNpmRun.WaitForExit();
        return readOutput = pNpmRun.StandardOutput.ReadLine();
    }

Я считаю, что если вы используете как StandardInput, так и StandardOutput, вы должны использовать сделать это асинхронно, чтобы избежать взаимоблокировок.

Dour High Arch 09.04.2019 01:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
1 099
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте написать команду exit во входной поток cmd.

Проблема заключается в том, что отправленные вами команды (npm, newman) выполняются, затем управление возвращается в оболочку (cmd), которая затем ожидает отправки дополнительных данных пользователя. Вам нужно сказать ему выйти, отправив «exit». У вас должен быть только 1 вызов WaitForExit. WaitForExit ожидает завершения процесса cmd, а не отдельных команд, которые вы ему отправляете.

Далее следует переместить ReadToEndпосле процесс завершился (после WaitForExit). Вот вопрос, почему: ReadToEnd из стандартного вывода процесса и waitforexit

Итак, что-то вроде этого:

public string Runner ()
    {
        var psiNpm = new ProcessStartInfo
        {
            FileName = "cmd",
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            UseShellExecute = false
        };
        var pNpmRun = Process.Start(psiNpm);
        pNpmRun.StandardInput.WriteLine("npm install -g newman");
        pNpmRun.StandardInput.WriteLine("newman run " +
            "\"C:\\Postman\\Test.postman.json\" " +
            "--folder \"TestSearch\" " +
            "--environment \"C:\\Postman\\postman_environment.json\" " +
            "--disable-unicode");
        pNpmRun.StandardInput.WriteLine("exit");

        pNpmRun.WaitForExit();
        return pNpmRun.StandardOutput.ReadToEnd();

Вы также можете рассмотреть возможность добавления тайм-аута в файл WaitForExit. Если эти команды по какой-то причине застревают, ваш процесс вызова также застрянет в ожидании их завершения. Обычно лучше в конечном итоге потерпеть неудачу, чем иметь кучу зависших процессов. Затем вы можете убить процесс, если истечет время ожидания.

  var tenMin = 10 * 60 * 1000;
  if (pNpmRun.WaitForExit(tenMin)) {
    return pNpmRun.StandardOutput.ReadToEnd();
  } else {
    pNpmRun.Kill();
    throw new TimeoutException("Command didn't complete in 10 minute timeout");
  }

Спасибо @MarkPflug! Это работает так, как мне нужно. Кстати, как мне настроить его, чтобы он не работал и убивал процесс, если cmd завис?

KVN 09.04.2019 17:12

@KVN Обновлено с примером тайм-аута. Обратите внимание, что если процессы npm или newman зависли, они будут уничтожены нет, только процесс cmd.

MarkPflug 09.04.2019 17:40

Большое спасибо @MarkPflug!

KVN 09.04.2019 18:23

@KVN Еще одна вещь, которую вы должны учитывать, - это поведение, если команды npm / newman по какой-то причине не работают. Предположительно, npm может дать сбой, если возникла проблема с сетью и т. д. Вероятно, вам следует проверить коды выхода ваших команд, и если они не равны нулю (сбои), то сообщить об этом вызывающей стороне, используя «exit% errorlevel%». Если вам нужна помощь с этим, вероятно, лучше всего открыть новый вопрос.

MarkPflug 09.04.2019 19:55

Спасибо @MarkPflug. На самом деле, это теперь моя настоящая проблема, если есть проблема с выполнением Newman - он просто зависает и переходит в часть сбоя/убийства IF. Для этого я создал еще один тикет (может быть, вы поможете и с этим): stackoverflow.com/questions/55600299/…

KVN 09.04.2019 21:51

извините, @MarkPflug, похоже, что мое текущее выполнение всегда завершается ошибкой WaitForExit, независимо от того, указываю ли я 0 мс или 10 минут, оно всегда переходит в часть условия Process.Kill(). Но команда newman выполнилась за 2-5 сек. Любые мысли о том, что происходит (неправильно) с ним? Я могу создать новый вопрос, если это необходимо.

KVN 11.04.2019 00:53

Другие вопросы по теме