Можно ли записать сообщение в cmd.exe в C # /. Net? - PullRequest
5 голосов
/ 01 июля 2011

Можно ли записать сообщение из приложения WinForms в программу cmd.exe, запущенную программным способом? Я пытался сделать все виды вариаций следующего кода:

private void button1_Click(object sender, EventArgs e)
{
    Log("Button has been pressed");
}

private void Log(string message)
{
    var process = Process.Start(new ProcessStartInfo("cmd.exe", @"/K ""more""")
    {
        UseShellExecute = false,
        RedirectStandardInput = true,
    });
    process.StandardInput.WriteLine(message);
}

К сожалению, окно консоли мигает полсекунды и все.

Пожалуйста, не отвечайте, что я действительно хочу сделать, потому что сейчас мне просто любопытно, возможно ли это:)

Ответы [ 5 ]

6 голосов
/ 01 июля 2011

Вам повезло. Я только что решил это для игрушечного проекта генератора кода, который у меня был здесь.

Используя AttachConsole или AllocConsole Win32 API, вы можете достичь результата, просто используя System.Console.WriteLine (или Read, или Error.WriteLine и т. Д.), Как обычно.

Следующий фрагмент выясняет, когда приложение форм запускалось из окна консоли, и подключается к его родительской консоли; Если это не сработает, он создаст собственную консоль и не забудет оставить ее открытой (чтобы она не исчезла, например, до того, как пользователь сможет прочитать вывод).

    [DllImport("kernel32.dll")] static extern bool AllocConsole();
    [DllImport("kernel32.dll")] static extern bool AttachConsole(int pw);
    private static bool _hasConsole, _keepConsoleOpen;
    static private void EnsureConsole()
    {
        _hasConsole      =  _hasConsole || AttachConsole(-1);
        _keepConsoleOpen = !_hasConsole || _keepConsoleOpen;
        _hasConsole      =  _hasConsole || AllocConsole();
    }

    [STAThread]
    private static void Main(string[] args)
    {
          EnsureConsole();

          // the usual stuff -- your program

          if (_keepConsoleOpen)
          {
              Console.WriteLine("(press enter)...");
              Console.Read();
          }
    }
2 голосов
/ 02 июля 2011

Не окончательный ответ, но он должен помочь, по крайней мере, немного:

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

В любом случае я попробовал следующее:

Process process = Process.Start(new ProcessStartInfo("cmd.exe", "/K more") {
  UseShellExecute = false,
  RedirectStandardInput = true,
  RedirectStandardError = true,
  RedirectStandardOutput = false
});

private void button1_Click(object sender, EventArgs e) {
  Log("Button has been pressed");
  MessageBox.Show(process.StandardError.ReadToEnd());
}

private void Log(string message) {
  process.StandardInput.WriteLine(message);
}

После нажатия кнопки ваше приложение будет зависать (оно ожидает закрытия консоли, ReadToEnd буквально читает до конца).Когда вы закрываете консоль, вы получите сообщение с выводом ошибки:

The handle is invalid.
The handle is invalid.
The handle is invalid.
'Button' is not recognized as an internal or external command,
operable program or batch file.
The handle is invalid.
The handle is invalid.

Кажется, что невозможно перенаправить только вход без перенаправления вывода при запуске CMD.Я не уверен, почему, может быть, попытка различных параметров командной строки поможет.Я также попытался удалить команду «Больше» и записать в журнал «dir»:

Log("dir");

Результат был немного пугающим:

The handle is invalid.
...
There is not enough space on the disk.
The handle is invalid.
The handle is invalid.

Интересно, должен сказать!Похоже, вы открыли банку с червями: -)

1 голос
/ 01 июля 2011

Вы должны вставить команду паузы после печати в консоль.

Процесс завершается, как только выполняется команда, в результате чего вы видите мигание.

0 голосов
/ 01 июля 2011

Я думаю, что если вы строите свой проект как «Консольное приложение», вы получаете консоль и все еще можете открывать формы Windows. Создайте новый проект типа «Консольное приложение». Добавьте форму Windows в проект. В функции Main в Program.cs создайте экземпляр и отобразите форму, используя этот код:

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

Не уверен, что это идеальный способ сделать это. Но это работает.

0 голосов
/ 01 июля 2011

Насколько я знаю, я верю, что вы открыли CMD правильно. Но как только команда будет выполнена, консоль завершится. Это нормальное поведение.

Если вы выполняете .bat / .cmd, вы можете написать более одной команды, и если вы сделали «паузу» после этой команды, вы сможете увидеть, что произошло до завершения консоли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...