2011-12-27 8 views
0

別の質問で説明されている問題がいくつか発生した後Windowsコマンドプロンプトをシミュレートするアプリケーションを作成しました。すべてのコマンドは、 "CMD.exe/C [command]"を呼び出し、その標準出力/エラーをWinformにリダイレクトするProcessオブジェクトによって実行されます。プロセスは入力を待つコマンドでハングし、RedirectStandardInputは 'true'です

うまくいくが、ユーザーインタラクション(RedirectStandardInputがTRUE)を求める「時間」や「wmic」などの特定のコマンドを実行すると、フォームがクラッシュする。どのように私はこれを解決することができます(古典的なプロンプトのような)入力を待つカーソルを作る?

この

は、私は例えば、入力リダイレクトと今の出力を可能にするすべての部分をコメントしたコード

 Process cmdProcess = new Process(); 
     cmdProcess.StartInfo.FileName = "CMD.exe"; 
     cmdProcess.StartInfo.Arguments = "/C " + command; 
     cmdProcess.StartInfo.WorkingDirectory = this.workingDir; 
     cmdProcess.StartInfo.CreateNoWindow = true; 
     cmdProcess.StartInfo.UseShellExecute = false; 
     cmdProcess.StartInfo.RedirectStandardOutput = true; 
     cmdProcess.StartInfo.StandardOutputEncoding = Encoding.Default; 
     cmdProcess.StartInfo.RedirectStandardError = true; 
     cmdProcess.StartInfo.StandardErrorEncoding = Encoding.Default; 
     //cmdProcess.StartInfo.RedirectStandardInput = true; 

     cmdProcess.Start(); 
     StreamReader outputR = cmdProcess.StandardOutput; 
     StreamReader errorR = cmdProcess.StandardError; 
     //StreamWriter inputW = cmdProcess.StandardInput; 

     string output = outputR.ReadToEnd(); 
     string error = errorR.ReadToEnd(); 

     if (output.Length > 0) 
      this.textArea.AppendText(Environment.NewLine + output); 
     else if (error.Length > 0) 
      this.textArea.AppendErrorText(Environment.NewLine + error); 

で、「時間」コマンドでは、すべてのユーザー入力を尋ねるとすぐに返していません。もちろん、私はこの振る舞いを好きではない;)

C:\Users\Alessandro\Progetti\CMDProject\CMDProject\bin\Debug>time 
Ora corrente: 19:32:17,55 
Immettere nuova ora: 
C:\Users\Alessandro\Progetti\CMDProject\CMDProject\bin\Debug> 
+0

お電話の際/ WMICは、あなたがこのsychronousをやりたいと思っていますまたは非同期。?あなたがおそらくしようとしているもののSystem.Diagnostics.Processを適切に使用する方法に関する他の参考文献を持っているこのリンクをチェックしてください.. http://stackoverflow.com/questions/7502894/wmic-mangementclass-remotecommand-determining-when-それは終わった - stdout – MethodMan

答えて

1

私は私のコードを見て、あなたが設定しcallbascksを持っているように、それは見てdoesntの、過去に似た何かをした、これを試して、何に私の命令をchangindあなたはこれが役に立てば幸い、欲しい:あなたは別のスレッドを開始する場合は、私のコードで示すように最初は、閉じていることを確認してください...

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 

using System.Text; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.Threading; 
using System.Globalization; 

namespace VSSWriterTest 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 


    public class VSSCommands 
    { 
     public string VSS_VSSExecutable = "vssadmin"; 
     public string VSS_VSSListWriters = " list writers"; 
    } 


    private void Form1_Load(object sender, EventArgs e) 
    { 
     //close handler 
     this.FormClosing+=new FormClosingEventHandler(Form1_FormClosing); 

    } 

    private void Form1_FormClosing(object sender, EventArgs e) 
    { 

    } 

    //my thread and process vars 
    private Process m_Process; 
    private Thread m_OutputThread; 
    private Thread m_ErrorThread; 
    private string m_TextToAdd; 

    //basic writer command line stuff 
    public class WriterStats 
    { 
     public string WriterName = "Writer Name"; 
     public string WriterTD = "Writer Id"; 
     public string WriterInstanceId = "Writer Instance Id"; 
     public string WriterState = "State"; 
     public string WriterLastError = "Last error"; 
     public string NoError = "No error"; 
    } 



    private void StartVSSDiagnostics() 
    { 
     try 
     { 
      this.rtbVSSList.Clear(); 
      iErrorCount = 0; 
      iWriterCount = 0; 
      this.txtErrors.Clear(); 

      //start cmd prompt, then write command statement to console screen 
      if ((StartVSSDiagnosticsThreads())) 
      { 
       VSSCommands ServiceCall = new VSSCommands(); 

       string msg = ServiceCall.VSS_VSSExecutable + ServiceCall.VSS_VSSListWriters; 
       VSSStreamInput(msg); 
      } 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, "EVAS Backup and Restore"); 
     } 
    } 

    private void VSSStreamInput(string Text) 
    { 
     try 
     { 
      if (Text != string.Empty) 
      { 
       m_Process.StandardInput.WriteLine(Text); 
       m_Process.StandardInput.Flush(); 
      } 

     } 
     catch (Exception ex) 
     { 
     } 
    } 

    private bool StartVSSDiagnosticsThreads() 
    { 

     try 
     { 
      //close threads if open 
      CloseThreads(); 

      //start new cmd prompt thread 
      m_Process = new Process(); 
      { 
       m_Process.StartInfo.FileName = "cmd"; 
       m_Process.StartInfo.UseShellExecute = false; 
       m_Process.StartInfo.CreateNoWindow = true; 
       m_Process.StartInfo.RedirectStandardOutput = true; 
       m_Process.StartInfo.RedirectStandardError = true; 
       m_Process.StartInfo.RedirectStandardInput = true; 

      } 
      m_Process.Start(); 

      //create the call backs 
      m_OutputThread = new Thread(StreamOutput); 
      m_OutputThread.IsBackground = true; 
      m_OutputThread.Start(); 
      m_ErrorThread = new Thread(StreamError); 
      m_ErrorThread.IsBackground = true; 
      m_ErrorThread.Start(); 

      return true; 
     } 
     catch (Exception ex) 
     { 
      return false; 
     } 
    } 

    //this stream is feedback from the command prompt, its a delegate thats on a seperate thread other than this UI 
    private void StreamOutput() 
    { 
     try 
     { 
      string Line = m_Process.StandardOutput.ReadLine(); 

      while (Line.Length >= 0) 
      { 
       if (Line.Length > 0) 
       { 
        ConsoleMessage(ConvertFromOem(Line)); 
       } 
       Line = m_Process.StandardOutput.ReadLine(); 
      } 
     } 
     catch 
     { 
      //ConsoleMessage(String.Format("""{0}"" Error!", m_Process.StartInfo.FileName)) 
     } 
    } 


    //convert text encoding to readable characters 
    private string ConvertFromOem(string Text) 
    { 
     try 
     { 
      return Encoding.GetEncoding(CultureInfo.InstalledUICulture.TextInfo.OEMCodePage).GetString(Encoding.Default.GetBytes(Text)); 
     } 
     catch (Exception ex) 
     { 
      return string.Empty; 
     } 
    } 

    //stream error callback 
    private void StreamError() 
    { 
     try 
     { 
      string Line = m_Process.StandardError.ReadLine(); 

      while (Line.Length >= 0) 
      { 
       Line = m_Process.StandardError.ReadLine(); 
       if (Line.Length > 0) 
       { 
        ConsoleMessage(Line, true); 
       } 
      } 
     } 
     catch 
     { 
      //ConsoleMessage(String.Format("""{0}"" Error!", m_Process.StartInfo.FileName)) 
     } 
    } 

    //actual delegate that invokes the main thread 
    private void ConsoleMessage(string Text, bool err = false) 
    { 
     try 
     { 
      if (err) 
      { 
       m_TextToAdd = "ERROR: " + Text; 
      } 
      else 
      { 
       m_TextToAdd = Text; 
      } 

      this.Invoke((MethodInvoker)this.RaiseConsoleTextEvent); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 


    //raise text event, new text arrived from console 
    private void RaiseConsoleTextEvent() 
    { 
     try 
     { 
      VSSMessages(m_TextToAdd); 

     } 
     catch (Exception ex) 
     { 
     } 
    } 


    //my message filter, what i want displayed on my UI, i parse microsoft logo and garbage to display results only 
    private int iErrorCount = 0; 
    private int iWriterCount = 0; 
    private void VSSMessages(string e) 
    { 
     WriterStats IWriter = new WriterStats(); 


     if ((e.ToUpper().Contains(IWriter.WriterInstanceId.ToUpper()) | e.ToUpper().Contains(IWriter.WriterLastError.ToUpper()) | 
      e.ToUpper().Contains(IWriter.WriterName.ToUpper()) | e.ToUpper().Contains(IWriter.WriterState.ToUpper()) | 
      e.ToUpper().Contains(IWriter.WriterTD.ToUpper()))) 
     { 
      if ((e.ToUpper().Contains(IWriter.WriterName.ToUpper()))) 
      { 
       iWriterCount += 1; 
       this.rtbVSSList.AppendText("Writer (" + iWriterCount.ToString() + ") " + e + Environment.NewLine); 
      } 
      else 
      { 
       this.rtbVSSList.AppendText(e + Environment.NewLine); 
      } 

      if ((e.ToUpper().Contains(IWriter.WriterLastError))) 
      { 
       if ((e.ToUpper().Contains(IWriter.NoError))) 
       { 
        iErrorCount += 1; 
        this.txtErrors.ForeColor = Color.Red; 
       } 
      } 

      this.txtErrors.Text = iErrorCount.ToString() + " Errors found in " + iWriterCount.ToString() + " system writers."; 

      if ((e.ToUpper().Contains(IWriter.WriterLastError.ToUpper()))) 
      { 
       this.rtbVSSList.AppendText(Environment.NewLine); 
      } 

      Application.DoEvents(); 

     } 


    } 

    //close any open threads, dont want run away threads! 
    private void CloseThreads() 
    { 
     try 
     { 
      if (((m_OutputThread != null))) 
      { 
       if ((m_OutputThread.IsAlive)) 
       { 
        m_OutputThread.Abort(); 
       } 
      } 

      if (((m_ErrorThread != null))) 
      { 
       if ((m_ErrorThread.IsAlive)) 
       { 
        m_ErrorThread.Abort(); 
       } 
      } 

     } 
     catch (Exception ex) 
     { 
     } 
    } 

    private void btnRun_Click(object sender, EventArgs e) 
    { 
     //begin 
     StartVSSDiagnostics(); 
    } 


} 

}

関連する問題