2013-10-23 106 views
0

首先,我花了相當一段時間試圖找到我的問題的答案,但到目前爲止,什麼都沒有。實時控制檯重定向問題

這是問題。 我必須運行帶有參數的cli命令並將輸出(REALTIME)重定向到文本框。 的命令看起來就像這樣: SMCLI - N的命名-f「script.scr」

由於SMCLI不是系統PATH變量,我首先需要去正確的迪爾

所以,我最終運行的完整的命令看起來像這樣: CMD/C CD 「C:\ Program Files文件(x86)的\喇嘛\」 & & SMCLI - N的命名-f 「script.scr」

我把在一秒鐘內的代碼,但基本上,這個事情工作得很好,我到了正確的目錄,運行命令,它運行腳本,都很好。

我試圖將輸出重定向到一個不同的窗體,但它不再工作了;無論如何,這將是獎金問題。

的事情是,雖然,在腳本運行時,它說的一步步它在做什麼,併發送到輸出信息(即恢復名稱,恢復磁盤配置,...)

正如我所說,一旦一切完成(即在5分鐘明顯凍結後),我確實得到了所有這些輸出。 不重定向輸出到文本框(即保持控制檯窗口打開),我得到輸出實時。

因此,這裏是現在的代碼(有一點吧,不好意思):

Private Sub ReadMDcfgToolStripButton_Click(sender As Object, e As EventArgs) Handles ReadMDcfgToolStripButton.Click 
     Dim exitcode As Int32 
     smcli = Environment.GetEnvironmentVariable("ProgramFiles") & "\Dell\MD Storage Manager\client\" 'SMcli.exe" 
     Dim gotosmclidir As String = "cd """ & smcli & """" 
     Dim smclicommand As String 
      smclicommand = "smcli -n " & mdname & " -c ""save storagearray configuration file=\""" & saveFileDialog2.FileName & "\"" allconfig"";" 
      cmd = gotosmclidir & " && " & smclicommand 
      exitcode = RunCommandCom(cmd, "", False) 
End Sub 

Private Function RunCommandCom(command As String, arguments As String, permanent As Boolean) As Int32 
    ' Usage: 
    'RunCommandCom("DIR", "/W", true) 
    'For the multiple command on one line the key are the & | && and || command connectors 
    '•A & B -> execute command A, then execute command B. 
    '•A | B -> execute command A, and redirect all it's output into the input of command B. 
    '•A && B -> execute command A, evaluate the errorlevel after running Command A, and if the exit code (errorlevel) is 0, only then execute command B. 
    '•A || B -> execute Command A, evalutate the exit code of this command and if it's anything but 0, only then execute command B. 

    TextBox1.Text = "Communication in progress..." & vbCrLf 
    exitcodelbl.Text = "" 
    CmdCloseBtn.Enabled = False 
    ToolStrip1.Enabled = False 
    CmdOutputPanel.Visible = True 

    Dim p As Process = New Process() 
    Dim pi As ProcessStartInfo = New ProcessStartInfo() 


    pi.FileName = "cmd.exe" 
    pi.Arguments = " " + If(permanent = True, "/K", "/C") + " " + command + " " + arguments 
    MsgBox(pi.Arguments) 
    pi.CreateNoWindow = True 
    pi.UseShellExecute = False 
    pi.RedirectStandardOutput = True 
    pi.RedirectStandardError = True 
    pi.CreateNoWindow = True 
    p.StartInfo = pi 
    AddHandler p.OutputDataReceived, AddressOf GotData 
    p.Start() 
    p.BeginOutputReadLine() 

    Do Until p.HasExited 
    Loop 

    exitcodelbl.Text = p.ExitCode 
    Select Case p.ExitCode 
     Case 0 
      exitcodelbl.Text += " - Command completed successfully." 
     Case 1 
      exitcodelbl.Text += " - Could not communicate with the Array." 
     Case 9 
      exitcodelbl.Text += " - Could not communicate with the Array." 
     Case 14 
      exitcodelbl.Text += " - Could not communicate with the Array." 
     Case Else 
      exitcodelbl.Text += " - Unknown code." 
    End Select 
    Return p.ExitCode 
End Function 

Sub GotData(ByVal sender As Object, ByVal e As DataReceivedEventArgs) 
    UpdateTextBox(e.Data) 
End Sub 

Private Delegate Sub UpdateTextBoxDelegate(ByVal Text As String) 

Private Sub UpdateTextBox(ByVal Tex As String) 
    If Me.InvokeRequired Then 
     Dim del As New UpdateTextBoxDelegate(AddressOf UpdateTextBox) 
     Dim args As Object() = {Tex} 
     Me.Invoke(del, args) 
    Else 
     TextBox1.Text &= Tex & Environment.NewLine 
    End If 
End Sub 

除了命令本身,一切從研究正在添加和他們只是放在一起,順便一方面運行命令,另一方面重定向。

我相信這個問題是與我的命令(看起來像那部分是非常明智的)。

要麼我可以用不同的方式完成它(再次,它的工作原理,但不是實時的),或者我錯過了一些微不足道的東西......?

感謝您的幫助。

這裏繼tinstaafl是更新後的代碼:

Private Sub MainForm_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown 
    copyrightlbl.Focus() 
    wait(1000) 
    Await RunCommandCom("", "192.168.219.152", False) '172.16.1.55 
    CmdCloseBtn.Enabled = True 
End Sub 

Private Async Function RunCommandCom(command As String, arguments As String, permanent As Boolean) As Task(Of Int32) 
    TextBox1.Text = "Communication in progress..." & vbCrLf 
    exitcodelbl.Text = "" 
    CmdCloseBtn.Enabled = False 
    ToolStrip1.Enabled = False 
    CmdOutputPanel.Visible = True 

    Dim p As Process = New Process() 
    With p.StartInfo 
     .WorkingDirectory = Environment.GetEnvironmentVariable("ProgramFiles") & "\Dell\MD Storage Manager\client\" 'Directory for SMcli.exe" 
     .FileName = "ping.exe" 
     .Arguments = command + " " + arguments 
     .CreateNoWindow = True 
     .UseShellExecute = False 
     .RedirectStandardOutput = True 
     .RedirectStandardError = True 
    End With 

    p.Start() 

    Do Until p.HasExited 
     TextBox1.Text &= Await p.StandardOutput.ReadLineAsync 
    Loop 
    exitcodelbl.Text = p.ExitCode 
    Return p.ExitCode 
End Function 
+0

如果腳本是爲了在控制檯中運行,是不是可以在它自己的控制檯中運行而不是使用cmd控制檯? – tinstaafl

+0

感謝您的回覆。我可能不能,因爲1)我必須從特定路徑運行命令,所以必須先導航到它2)基於cli的應用程序不在Windows中的PATH var(並且不,我不能擁有它添加因爲我會更改Windows配置,這是一個完整的NO-NO) – Nick

+0

您可以在Filename屬性中將整個路徑設置爲可執行文件。無需嘗試使用PATH或在任何地方導航。如果可執行文件需要特定的工作目錄,請在startInfo屬性 – tinstaafl

回答

2

而是採用委託嘗試直接讀取輸出到文本框。 Process的StandardOutput屬性是一個可以使用ReadLineAsync方法獲取輸出的流。像這樣的東西應該工作:

pi.CreateNoWindow = True 
pi.UseShellExecute = False 
pi.RedirectStandardOutput = True 
pi.RedirectStandardError = True 
p.StartInfo = pi 
p.Start() 

Do Until p.HasExited 
    TextBox1.Text &= Await p.StandardOutput.ReadLineAsync 
Loop 

智能感知會提示你做的子程序異步,但你應該得到你想要的輸出。

Private Async Function RunCommandCom(command As String, arguments As String, permanent As Boolean) As Task(Of Int32) 


Await RunCommandCom("", "192.168.219.152", False) 
+0

事實上,我得到這個:錯誤'等待'只能用於異步方法。考慮使用'Async'修飾符標記此方法並將其返回類型更改爲'Task(Of Integer)'。請原諒我的無知,但如何處理它。再一次,試圖看看,但不明白我在讀什麼,因爲它的工作方式在我的知識之外。 – Nick

+0

異步修飾符在函數或子關鍵字 – tinstaafl

+0

之前我是sory,但你失去了我的傢伙。 :-( – Nick