2015-10-12 3 views
1

То, что я намереваюсь сделать, это создать приложение, в котором, помимо прочего, будет встроена встроенная в него командная строка, как это делают некоторые IDE (что-то мне очень полезно).Внедрение CMD-терминала в приложение Winforms C#

Это код, который я до сих пор, не отметить, что это проект Winforms:

public partial class Form1 : Form 
    { 
     Process p = new Process(); 
     ProcessStartInfo info = new ProcessStartInfo(); 

     public Form1() { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) { 
      info.FileName = "cmd.exe"; 
      info.RedirectStandardInput = true; 
      info.RedirectStandardOutput = true; 
      info.RedirectStandardError = true; 
      info.UseShellExecute = false; 
      info.CreateNoWindow = true; 

      p.StartInfo = info; 
      p.Start(); 
     } 

     private void button1_Click(object sender, EventArgs e) { 
      using(StreamWriter sw = p.StandardInput) { 
       if(sw.BaseStream.CanWrite) { 
        sw.WriteLine(textBox1.Text); 
       } 
      } 
      textBox2.Text = p.StandardOutput.ReadToEnd(); 
      textBox3.Text = p.StandardError.ReadToEnd(); 
      p.WaitForExit(); 
     } 
    } 
} 

Как вы можете видеть, что есть 3 текстовые поля и одна кнопка:

  • TextBox1 для введя команду
  • TextBox2 для стандартного вывода
  • textbox3 для STDERR

На моей проблемы:

я могу ввести только один команду, потому что после его выполнения, мое окно CMD исчезает. Я знаю, что он исчезает, потому что я установил info.CreateNoWindow = false;, и он действительно исчезнет, ​​и если я попытаюсь ввести другую команду, я получаю исключение.

Как бы я продолжал поддерживать мое окно CMD «живым», чтобы я мог использовать его так, как мне нравится? Короче говоря, я хочу по-настоящему имитировать поведение CMD.

Не стесняйтесь спрашивать дополнительную информацию, если что-то неясно.

Extra информация/Что я пробовал:

Я пытался добавить info.Attributes = "/K";, так как я знаю, что /K должен держать CMD жив. Я также читал, что p.WaitForExit(); должен сохранять CMD в живых, но из того, что я понял, это только для того, чтобы читать результат. Излишне говорить, что мне это не нужно, поскольку я уже перенаправляю его вывод. Ни одно из этих решений не работает, но вполне возможно, что я использую их неправильно.

мне нужно этот процесс живой, чтобы я мог легко перемещаться с помощью cd и выполнения последовательности команд, когда это необходимо, например, при доступе к ftp или mysql. Я знаю, что могу обойти эти два примера с параметрами, но не для каждого приложения. Короче говоря, нереста нового процесса каждый раз не то, что я хочу. Я хочу, чтобы интерфейс CMD постоянно работал.

ЦМД процесс умирает после того, как

using(StreamWriter sw = p.StandardInput) { 
    if(sw.BaseStream.CanWrite) { 
     sw.WriteLine(textBox1.Text); 
    } 
} 

Но я не могу точно определить, почему.

+0

Это выражение 'using' вызывает' p.StandardInput' для удаления ('sw' - это просто ссылка на него). Не делайте этого - удаляйте 'p' вместо (когда вам это больше не нужно). –

+0

@PieterWitvoet Спасибо за ваш ответ. Таким образом, в основном p удаляется, когда я оставляю область использования? Как я буду продолжать использовать StreamWriter без инструкции 'using'? Я попытался объявить StreamWriter в методе 'Form1_Load' и впоследствии получить доступ к выходному' p.StandardOutput', но мое приложение зависает без каких-либо исключений. Не могли бы вы уточнить, пожалуйста? – xIcarus

+0

Независимо от того, что вы используете, используется в конце блока 'using', поэтому каждый раз, когда вы вводите команду, ваш код удаляет стандартный ввод вашего процесса. Вы по существу распоряжаетесь частью объекта и ожидаете, что он продолжит работу, как раньше. Просто удалите этот оператор 'using'. 'sw' - это не новый писатель потока, за который вы отвечаете - это ссылка на' p.StandardInput'. Устранение 'p' позаботится об утилизации этих потоковых писателей для вас. –

ответ

0

Консоль CMD предоставляет интерфейс для выполнения предопределенных функций (в System32 или% PATH%). Класс класс также имеет те же возможности, что вы можете сделать, так как пользователь вводит текст команды и нажимает клавишу возврата в текстовое поле2 (которое может быть многослойным, черно-фоновым, белым текстом), вы можете передать текст команды Process p = new Process(); и добавьте результат, чтобы он выглядел как single cmd session. Теперь перед передачей всего текста команды нам нужно отделить аргументы (если они есть), которые появляются после первого пробела.Пример:

SHUTDOWN /S /T 10 

где Shutdown будет filename и/S/T 10 будут аргументами.

Перед выполнением заданного каталога ProcessStartInfo по умолчанию: -

_processStartInfo.WorkingDirectory = @"%Path%"; 

В противном случае по умолчанию будет папка System32.

+0

Это на самом деле идея, о которой я также думал и реализовал ее в приложении на C++ некоторое время назад. К сожалению, это просто тень реальной вещи, симуляция, обходной путь. Не настоящее решение. Именно поэтому я переписываю подобное приложение на C#. Но спасибо за ваш вклад, я сохраню это в крайнем случае. – xIcarus

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