2010-11-05 19 views
9

Soru: cmd.exe'yi winform'lardan denetlemek istiyorum.

Her komut tek bir işlemde, startupinfo ile durmayın ve sonra dur. Ben mesela demek

istemi
çıkış işlemi SQL komutu durdurmak, sonraki cevap almak, bir sonraki komutu göndermek, cevap almak, komutu göndermek, (My), SQL veya GDB komut istemi başlatın.

Temel olarak herhangi bir konsol uygulamasının üstüne bir GUI yazmak istiyorum.

Bir metin alanına yönlendirilen cmd.exe çıkışını ve başka bir metin alanından gelen girişi (basında gir/Tamam düğmesi) almak istiyorum.Winforms'dan cmd.exe'yi denetleme

Bunun için herhangi bir örnek bulamıyorum. Bir yolu var mı?

cevap

16

CodeProject

İyi şanslar güzel bir örnek vardır!

-Edit: Bunun daha çok olduğunu düşünüyorum, basit bir form, 2 metin kutusu ve üç düğme oluşturdum. İlk metin kutusu komut girişi içindir, ikincisi (çok satırlı) sonucu görüntüler.

ilk düğme komutunu çalıştırır, ikinci düğme ben dizin ve sonraki değiştirmek için cd \ komutunu girdiğini görebilirsiniz ekran görüntüsünde (sonuçlar okunur çünkü zaman uyumsuz)

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     private static StringBuilder cmdOutput = null; 
     Process cmdProcess; 
     StreamWriter cmdStreamWriter; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      cmdOutput = new StringBuilder(""); 
      cmdProcess = new Process(); 

      cmdProcess.StartInfo.FileName = "cmd.exe"; 
      cmdProcess.StartInfo.UseShellExecute = false; 
      cmdProcess.StartInfo.CreateNoWindow = true; 
      cmdProcess.StartInfo.RedirectStandardOutput = true; 

      cmdProcess.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler); 
      cmdProcess.StartInfo.RedirectStandardInput = true; 
      cmdProcess.Start(); 

      cmdStreamWriter = cmdProcess.StandardInput; 
      cmdProcess.BeginOutputReadLine(); 
     } 

     private void btnExecute_Click(object sender, EventArgs e) 
     { 
      cmdStreamWriter.WriteLine(textBox2.Text); 
     } 

     private void btnQuit_Click(object sender, EventArgs e) 
     { 
      cmdStreamWriter.Close(); 
      cmdProcess.WaitForExit(); 
      cmdProcess.Close(); 
     } 

     private void btnShowOutput_Click(object sender, EventArgs e) 
     { 
      textBox1.Text = cmdOutput.ToString(); 
     } 

     private static void SortOutputHandler(object sendingProcess, 
      DataReceivedEventArgs outLine) 
     { 
      if (!String.IsNullOrEmpty(outLine.Data)) 
      { 
       cmdOutput.Append(Environment.NewLine + outLine.Data); 
      } 
     } 
    } 
} 

sonucu günceller Bu dizinde çalıştırılan komut (dir). alt text

+0

Merhaba, Ctrl + C komutunu nasıl yazabilirim? –

2

Bunun için birlikte çalışmanıza gerek yoktur. .NET Process sınıfı size ihtiyacınız olan her şeyi verir, standart giriş akışını ve çıktı akışını yeniden yönlendirir ve tamamlanır. İnternette bunun nasıl yapılacağını birçok örnek bulabilirsiniz.

+1

Evet, ancak, komutların bir diğerini birbiri ardına birkaç komut vermek isterseniz, bu komut, ikinci komutun derleme zamanında bilinmediği anlamına gelir. Ve bunun için işe yarayan hiçbir şey bulamazsın. –

1

Bunun için cmd.exe'yi kullanmanız gerekmez, komutları doğrudan Process.Start() ile arayabilirsiniz. StandardInput ve StandardOutput'ı yönlendirirseniz, işlemi kontrol edebilirsiniz.

another question'a bir yanıt olarak bir örnek yazdım.

Düzenleme
bunun için eksiksiz bir örnek yok, ama eşzamanlı beklemek istemiyorsanız size Process.OutputDataReceived olayla StandardOutput dinleyebilirim. MSDN sayfasında bir örnek var.

+0

Bu hiçbir şekilde problemi çözmez. Çıkışı okumak için giriş akışını kapatır, ancak bu noktadan sonra başka komutlar göndermek mümkün değildir. –

+0

@Quandary, Cevabınızı, sizin durumunuzda daha kullanışlı olabilecek olan OutputDataReceived olayına yönelik bir bağlantıyla güncelledim. –

0

Bu mükemmel cevabı: Ben cezbetmek outputstream.Peek() ile çalıştı hakkında çıkan ilk

using System; 
using System.Windows.Forms; 


namespace WindowsConsole 
{ 


    public partial class Form1 : Form 
    { 
     System.Diagnostics.Process spdTerminal; 
     System.IO.StreamWriter swInputStream; 


     public delegate void fpTextBoxCallback_t(string strText); 
     public fpTextBoxCallback_t fpTextBoxCallback; 


     public Form1() 
     { 
      fpTextBoxCallback = new fpTextBoxCallback_t(AddTextToOutputTextBox); 
      InitializeComponent(); 
     } // End Constructor 


     public void AddTextToOutputTextBox(string strText) 
     { 
      this.txtOutput.AppendText(strText); 
     } // End Sub AddTextToOutputTextBox 


     private void btnQuit_Click(object sender, EventArgs e) 
     { 
      swInputStream.WriteLine("exit"); 
      swInputStream.Close(); 
      //spdTerminal.WaitForExit(); 
      spdTerminal.Close(); 
      spdTerminal.Dispose(); 
      Application.Exit(); 
     } // End Sub btnQuit_Click 


     private void ConsoleOutputHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) 
     { 
      if (!String.IsNullOrEmpty(outLine.Data)) 
      { 
       //this.Invoke(new fpTextBoxCallback_t(AddTextToOutputTextBox), Environment.NewLine + outLine.Data); 
       if(this.InvokeRequired) 
        this.Invoke(fpTextBoxCallback, Environment.NewLine + outLine.Data); 
       else 
        fpTextBoxCallback(Environment.NewLine + outLine.Data); 
      } // End if (!String.IsNullOrEmpty(outLine.Data)) 

     } // End Sub ConsoleOutputHandler 


     private void btnExecute_Click(object sender, EventArgs e) 
     { 
      if (this.spdTerminal.HasExited) 
      { 
       MessageBox.Show("You idiot, you have terminated the process", "Error"); 
       return; 
      } // End if (this.spdTerminal.HasExited) 

      swInputStream.WriteLine(txtInputCommand.Text); 
     } // End Sub btnExecute_Click 


     public void ProcessExited(object sender, EventArgs e) 
     { 
      MessageBox.Show("You idiot, you terminated the process.", "PBKAC"); 
     } // End Sub ProcessExited 


     private void Form1_Load(object sender, EventArgs e) 
     { 
      spdTerminal = new System.Diagnostics.Process(); 

      if(Environment.OSVersion.Platform == PlatformID.Unix) 
       //spdTerminal.StartInfo.FileName = "/usr/bin/gnome-terminal"; 
       spdTerminal.StartInfo.FileName = "/bin/bash"; 
      else 
       spdTerminal.StartInfo.FileName = "cmd.exe"; 

      AddTextToOutputTextBox("Using this terminal: " + spdTerminal.StartInfo.FileName); 

      spdTerminal.StartInfo.UseShellExecute = false; 
      spdTerminal.StartInfo.CreateNoWindow = true; 
      spdTerminal.StartInfo.RedirectStandardInput = true; 
      spdTerminal.StartInfo.RedirectStandardOutput = true; 
      spdTerminal.StartInfo.RedirectStandardError = true; 

      spdTerminal.EnableRaisingEvents = true; 
      spdTerminal.Exited += new EventHandler(ProcessExited); 
      spdTerminal.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(ConsoleOutputHandler); 
      spdTerminal.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(ConsoleOutputHandler); 

      spdTerminal.Start(); 

      swInputStream = spdTerminal.StandardInput; 
      spdTerminal.BeginOutputReadLine(); 
      spdTerminal.BeginErrorReadLine(); 
     } // End Sub Form1_Load 


    } // End Class Form1 


} // End Namespace WindowsConsole 

= -1 ama bu gelmez .NET framework Peek işlevi bir hata ile çöktü alır Zaman aşımı ya da akış sonunu okursanız bir hata atıyor ...

Tüm çıktıları yakaladığından daha iyi çalışır, ancak mükemmel olmaktan uzaktır.

Public Class Form1 


    ' That's our custom TextWriter class 
    Private _writer As System.IO.TextWriter = Nothing 

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing 
     If p IsNot Nothing Then 
      p.Close() 
      p.Dispose() 
      p = Nothing 
     End If 
    End Sub 


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     InitProcess() 
     '' Instantiate the writer 
     '_writer = New ConsoleRedirection.TextBoxStreamWriter(Me.txtConsole) 
     '' Redirect the out Console stream 
     'Console.SetOut(_writer) 
     'Console.WriteLine("Now redirecting output to the text box1") 
     'Console.WriteLine("Now redirecting output to the text box2") 
    End Sub 

    Protected p As Process 
    Protected sw As System.IO.StreamWriter 
    Protected sr As System.IO.StreamReader 
    Protected err As System.IO.StreamReader 


    Protected objWriter As System.IO.StreamWriter 
    Protected objWriteNumeric As System.IO.StreamWriter 

    Private Sub InitProcess() 
     p = New Process() 

     Dim psI As New ProcessStartInfo("cmd") 
     psI.UseShellExecute = False 
     psI.RedirectStandardInput = True 
     psI.RedirectStandardOutput = True 
     psI.RedirectStandardError = True 
     psI.CreateNoWindow = True 
     p.StartInfo = psI 
     p.Start() 
     sw = p.StandardInput 
     sr = p.StandardOutput 
     err = p.StandardError 
     sw.AutoFlush = True 


     objWriter = New System.IO.StreamWriter("c:\temp\logmy.txt", True, System.Text.Encoding.ASCII) 
     objWriteNumeric = New System.IO.StreamWriter("c:\temp\lognum.txt", True, System.Text.Encoding.ASCII) 



     Timer1.Enabled = True 
     Timer1.Start() 

    End Sub 

    Private Sub start() 

     If Me.txtinput.Text <> "" Then 
      sw.WriteLine(Me.txtinput.Text) 
     Else 
      'execute default command 
      sw.WriteLine("dir c:\music") 
     End If 
     sw.Flush() 

     Timer2.Enabled = True 
    End Sub 


    Private Sub start_original() 
     p = New Process() 
     Dim sw As System.IO.StreamWriter 
     Dim sr As System.IO.StreamReader 
     Dim err As System.IO.StreamReader 
     Dim psI As New ProcessStartInfo("cmd") 
     psI.UseShellExecute = False 
     psI.RedirectStandardInput = True 
     psI.RedirectStandardOutput = True 
     psI.RedirectStandardError = True 
     psI.CreateNoWindow = True 
     p.StartInfo = psI 
     p.Start() 
     sw = p.StandardInput 
     sr = p.StandardOutput 
     err = p.StandardError 
     sw.AutoFlush = True 

     Me.txtinput.Text = "help" 

     If Me.txtinput.Text <> "" Then 
      sw.WriteLine(Me.txtinput.Text) 
     Else 
      'execute default command 
      sw.WriteLine("dir \") 
     End If 
     sw.Close() 



     'Me.txtConsole.Text = sr.ReadToEnd() 

     'txtinput.Text = sr.ReadToEnd() 
     'txtinput.Text += err.ReadToEnd() 
    End Sub 



    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     start() 
    End Sub 




    Protected sb As String = "" 
    Sub ReadOutputStreamIfAvailable() 
     'cbEndOfStream.Checked = sr.EndOfStream 

     While True 
      objWriteNumeric.WriteLine(sr.Peek().ToString()) 
      objWriteNumeric.Flush() 



      If sr.Peek = -1 Then 
       Exit While 
      End If 


      Dim iCharAsNumber As Integer = sr.Read() 

      Dim cNumberAsChar As Char = Nothing 
      If Not iCharAsNumber = Nothing Then 
       Try 
        cNumberAsChar = Chr(iCharAsNumber) 
       Catch 
        Continue While 
        'MsgBox(Prompt:=xx.ToString, Title:="Error") 
        'Exit While 
       End Try 

      End If 

      Dim strCharAsString As String = "" 
      If Not cNumberAsChar = Nothing Then 
       strCharAsString = cNumberAsChar.ToString() 
      End If 

      sb += strCharAsString 
     End While 


     If Not String.IsNullOrEmpty(sb) Then 
      'MsgBox(sb) 
      MsgBox(sb) 
      Me.txtConsole.Text += sb 
      'MsgBox(sb) 
      sb = "" 
     End If 
    End Sub 






    Protected er As String = "" 
    Sub ReadErrorStreamIfAvailable() 
     'cbEndOfStream.Checked = sr.EndOfStream 

     While True 
      objWriteNumeric.WriteLine(sr.Peek().ToString()) 
      objWriteNumeric.Flush() 


      If err.Peek = -1 Then 
       Exit While 
      End If 


      Dim iCharAsNumber As Integer = err.Read() 

      Dim cNumberAsChar As Char = Nothing 
      If Not iCharAsNumber = Nothing Then 
       Try 
        cNumberAsChar = Chr(iCharAsNumber) 
       Catch 
        Continue While 
        'MsgBox(Prompt:=xx.ToString, Title:="Error") 
        'Exit While 
       End Try 

      End If 

      Dim strCharAsString As String = "" 
      If Not cNumberAsChar = Nothing Then 
       strCharAsString = cNumberAsChar.ToString() 
      End If 

      er += strCharAsString 
     End While 


     If Not String.IsNullOrEmpty(er) Then 
      'MsgBox(sb) 
      'MsgBox(er) 
      Me.txtConsole.Text += er 
      'MsgBox(sb) 
      er = "" 
     End If 
    End Sub 



    Protected Shared objOutputStreamLocker As Object = New Object 

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick 
     Timer1.Enabled = False 

     SyncLock objOutputStreamLocker 
      ReadOutputStreamIfAvailable() 
      'ReadErrorStreamIfAvailable() 
     End SyncLock 

     Timer1.Enabled = True 
    End Sub 


    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick 
     Try 
      Timer2.Enabled = False 
      sb = Chr(sr.Read()).ToString() 
      '' 
      'er = Chr(err.Read()).ToString() 
      '' 

      Timer1.Enabled = True 
     Catch ex As Exception 
      MsgBox("You have terminated the process", Title:="You idiot!") 
     End Try 
    End Sub 


    ' http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 

    End Sub 


End Class