0

まず第一に、私は自分の問題に対する答えを見つけるのにかなりの時間を費やしましたが、これまでのところ何もありません.

これが問題です。引数を指定して cli コマンドを実行し、出力 (REALTIME) をテキスト ボックスにリダイレクトする必要があります。コマンドは次のようになります: smcli - n name -f "script.scr"

smcli はシステム PATH 変数にないため、最初に正しい Dir に移動する必要があります。

したがって、次のような完全なコマンドを実行することになります: cmd /c cd "c:\Program Files(x86)\bla\" && smcli - n name -f "script.scr"

コードを 1 秒で説明しますが、基本的には問題なく動作しています。正しいディレクトリに移動し、コマンドを実行すると、スクリプトが実行されます。すべて問題ありません。

出力を別の形式にリダイレクトしようとしましたが、まったく機能しません。とにかく、それはおまけの質問です。

ただし、スクリプトが実行されると、スクリプトが実行していることを段階的に示し、その情報を出力に送信します (つまり、名前の復元、ディスク構成の復元など)。

私が言ったように、私はそれらすべての出力を取得します....すべてが完了すると(つまり、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
4

1 に答える 1

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) 
于 2013-10-24T17:10:14.607 に答える