Как получить ответ от приложения в командной строке cmd?

447
13 февраля 2017, 13:28

Например пишем C:\app.exe /h жмем Enter и получаем ответ "Команда выполнена".

Windows Form - C# (файл Program.cs)

Answer 1

Для этого есть несколько вариантов:

  • создать новую консоль:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using WindowsFormsApp2;
    static class Program
    {
      [STAThread]
      static void Main()
      {
        AllocConsole();
        Console.WriteLine("Hello");
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
      }
      [DllImport("kernel32.dll", SetLastError = true)]
      [return: MarshalAs(UnmanagedType.Bool)]
      static extern bool AllocConsole();
    }
    
  • приаттачится к консоли:

    public class GUIConsoleWriter
    {
      private const int ATTACH_PARENT_PROCESS = -1;
      StreamWriter _stdOutWriter;
      public GUIConsoleWriter()
      {
        var stdout = Console.OpenStandardOutput();
        _stdOutWriter = new StreamWriter(stdout);
        _stdOutWriter.AutoFlush = true;
        AttachConsole(ATTACH_PARENT_PROCESS);
      }
      [DllImport("kernel32.dll")]
      private static extern bool AttachConsole(int dwProcessId);
    }
    

Program.cs:

    static class Program
    {
      [STAThread]
      private static void Main()
      {
        var consoleWriter = new GUIConsoleWriter();
        Console.WriteLine("Hello");
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
      }
    }

То есть если Вы запускаете свое приложение с уже запущенной консоли, или с Far Manager то что бы получить результат в их окно вывода - используйте второй вариант. Первый если консоль нужно создать.

Источник: SO

P.S: не забудьте поблагодарить авторов оригинальных ответов =)

Answer 2

В .NET для запуска нового процесса используется статический метод Process.Start, который возвращает экземпляр класса Process. У этого класса есть свойство, которое предоставляет доступ к потоку, в который программа может выводить сообщения: StandardOutput. Доступ дается не напрямую, а через StreamReader, что даже удобнее. Для того, чтобы программа выводила результат не в консоль, а в StandardOutput, необходимо в свойствах процесса (ProcessStartInfo), включить опцию RedirectStandardOutput.

Если перед вами стоит задача запустить консольное приложение из своей программы и прочитать то, что оно выведет в консоль, воспользуйтесь методом Process.Start для запуска приложения, и используйте StreamReader полученный из StandardOutput, чтобы прочесть результат. Например, можно прочитать все данные которые содержит поток в текстовом формате используя метод ReadToEnd.

Но есть нюанс. Нельзя сразу взять и прочитать ответ, потому что процессу требуется некоторое время чтобы выполнить работу и вывести результат в консоль. Метод ReadToEnd будет ожидать завершения процесса. Если во время ожидания необходимо чтобы ваша программа продолжала функционировать (например перерисовывать окно, реагировать на действия пользователя), используйте метод ReadToEndAsync, который вызовет делегат по завершению и передаст ему результат, или метод ReadLine, который возвращает управление по мере получения строк, а не дожидается окончания процесса.

ProcessStartInfo startInfo = new ProcessStartInfo(@"C:\app.exe", @"/h");
// можно даже скрыть окно запущенного процесса
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
// указываем что программа должна выводить резульат в поток привязанный к свойству StandardOutput
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
// запускаем процесс
Process procCommand = Process.Start(startInfo);
// получаем ответ запущенного процесса
StreamReader srIncoming = procCommand.StandardOutput;
string result = srIncoming.ReadToEnd();

Пример взят и переработан из этой статьи: Запуск командной строки и получение ответа.

Answer 3

Код получился такой (надеюсь ошибок в нем нет):

using System;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var consoleWriter = new GUIConsoleWriter();
        var form = new Form1();
        bool needRun = true;
        foreach (string arg in args)
        {
            switch (arg)
            {
                case "/h":
                    Console.WriteLine("Команда выполнена");
                    form.Check1();
                    needRun = false;
                    break;
                case "/s":
                    Console.WriteLine("Команда выполнена");
                    form.Check2();
                    needRun = false;
                    break;
                case "/e":
                    Console.WriteLine("Команда выполнена");
                    form.Check3();
                    needRun = false;
                    break;
            }
        }
        if (needRun)
        {
            Application.Run(form);
        }
    }
    public class GUIConsoleWriter
    {
        private const int ATTACH_PARENT_PROCESS = -1;
        StreamWriter _stdOutWriter;
        public GUIConsoleWriter()
        {
            var stdout = Console.OpenStandardOutput();
            _stdOutWriter = new StreamWriter(stdout);
            _stdOutWriter.AutoFlush = true;
            AttachConsole(ATTACH_PARENT_PROCESS);
        }
        [DllImport("kernel32.dll")]
        private static extern bool AttachConsole(int dwProcessId);
    }
Answer 4

Нашел еще один более простой способ:

using System;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var form = new Form1();
        if (AttachConsole(-1))
        {
            foreach (string arg in args)
            {
                switch (arg)
                {
                    case "/h":
                        form.Check1();
                        Console.Write("\r\n" + "Команда /h выполнена");
                        break;
                    case "/s":
                        form.Check2();
                        Console.Write("\r\n" + "Команда /s выполнена");
                        break;
                    case "/e":
                        form.Check3();
                        Console.Write("\r\n" + "Команда /e выполнена");
                        break;
                }
            }
        }
        else
        {
            Application.Run(form);
        }
    }
    [DllImport("kernel32.dll")]
    private static extern bool AttachConsole(int procid);

Источник: ссылка

READ ALSO
Переход на другую версию Visual Studio, INotifyPropertyChanged

Переход на другую версию Visual Studio, INotifyPropertyChanged

Добрый день, пользовался VS2016Сейчас решил перейти на версию 2013, открыл проект на 2013 версии, мне начало выдавать ошибки при работе с INotifyPropertyChanged:

410
Обновить после добавления в БД (MySQL)

Обновить после добавления в БД (MySQL)

Добрый день, подскажите как обновить табличку по клику на кнопку:

365
Не удается записать в ListView

Не удается записать в ListView

Есть класс, содержащий строку String и целое число int

314
Доступ к массиву из другого класса

Доступ к массиву из другого класса

Здравствуйте, только начала изучать C#, столкнулся с такой проблемой

451