如何在 Visual Basic 中将 Shell 命令输出到 RichTextBox

How To Output Shell Command To a RichTextBox In Visual Basic

我整个星期都在为这个问题苦苦挣扎,所以我希望这里的专家能帮助我。我有一个可执行文件,它绝对必须是 运行 来自带有参数的命令行。我想要做的不是启动命令提示符 window,而是想将数据发送到我表单上的富文本框。

如果我设置一个批处理文件并 运行 批处理文件使用正确的代码(运行将其作为 Process),这没有问题。但是,我希望用户能够将自己的参数输入 TextBox 而不是创建批处理文件并引用它。

我只能通过调用 Shell 将此应用程序正确地获取到 运行。但是,我读到如果您正在使用 Call Shell,则无法将数据输出到 RichTextBox,并且需要将其设置为新的 Process。我似乎无法将此 运行ning 作为 Process.

所以问题是,是否有可能以某种方式将 Call Shell 数据输出到 RichTextBox 控件,或者有没有办法将此东西作为 运行过程?下面的 Visual Basic 代码会将其输出到 运行,但不会输出到 RichTextBox。我删除了我尝试过的所有代码,因为每次尝试都失败了。

此按钮将启动 Process,或者如果 Process 是 运行ning,它将终止它。

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim exeargs As String = txtExeArgs.Text
    Dim p1() As Process
    Dim strCommand As String = "executable.exe " & exeargs & ""
    p1 = Process.GetProcessesByName("executable")
    Dim exepath As String = IO.Path.GetDirectoryName(Me.txtExeLocation.Text)

    If p1.Count <= 0 Then

        RichTextBox1.Clear()

        Call Shell("cmd.exe /c cd /d " & exepath & " & " & strCommand, 0)

    Else
        Dim killprocess = System.Diagnostics.Process.GetProcesses().Where((Function(p) p.ProcessName = "executable"))
        For Each p As Process In killprocess
            p.Kill()
        Next
        RichTextBox1.Clear()
    End If
End Sub

使用System.Diagnostics.Process很有可能。
实际结果取决于该程序的实际工作方式。
它可能需要一些测试才能正确输出。

这是一个通用过程,您可以使用它来测试您的可执行文件是否以标准方式运行。
它使用 tracert.exe 并将其结果输出到 RichTextBox 控件中。

请注意 Process.Start() 初始化使用 Process.SynchronizingObject() set to the RichTextBox control Parent Form to avoid InvokeRequired. But if you don't want to use a Synch object, Control.Invoke is handled anyway, using MethodInvoker 委托。

要切换到您的可执行文件,请根据需要替换 StartProcess() 方法参数。

Imports System.Diagnostics
Imports System.IO

Private CurrentProcessID As Integer = -1

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    StartProcess("C:\Windows\System32\tracert.exe", "whosebug.com")
End Sub

Private Sub StartProcess(FileName As String, Arguments As String)

    Dim MyStartInfo As New ProcessStartInfo() With {
        .FileName = FileName,
        .Arguments = Arguments,
        .WorkingDirectory = Path.GetDirectoryName(FileName),
        .RedirectStandardError = True,
        .RedirectStandardOutput = True,
        .UseShellExecute = False,
        .CreateNoWindow = True
    }

    Dim MyProcess As Process = New Process() With {
        .StartInfo = MyStartInfo,
        .EnableRaisingEvents = True,
        ' Setting a SynchronizingObject, we don't need to BeginInvoke. 
        ' I leave it there anyway, in case there's no SynchronizingObject to set
        ' BeginInvoke can be used with or without a synchronization context.
        .SynchronizingObject = Me
    }

    MyProcess.Start()
    MyProcess.BeginErrorReadLine()
    MyProcess.BeginOutputReadLine()

    CurrentProcessID = MyProcess.Id

    AddHandler MyProcess.OutputDataReceived,
        Sub(sender As Object, e As DataReceivedEventArgs)
            If e.Data IsNot Nothing Then
                BeginInvoke(New MethodInvoker(
                Sub()
                    RichTextBox1.AppendText(e.Data + Environment.NewLine)
                    RichTextBox1.ScrollToCaret()
                End Sub))
            End If
        End Sub

    AddHandler MyProcess.ErrorDataReceived,
        Sub(sender As Object, e As DataReceivedEventArgs)
            If e.Data IsNot Nothing Then
                BeginInvoke(New MethodInvoker(
                Sub()
                    RichTextBox1.AppendText(e.Data + Environment.NewLine)
                    RichTextBox1.ScrollToCaret()
                End Sub))
            End If
        End Sub

    AddHandler MyProcess.Exited,
        Sub(source As Object, ev As EventArgs)
            MyProcess.Close()
            If MyProcess IsNot Nothing Then
                MyProcess.Dispose()
            End If
        End Sub
End Sub


:
如果您需要终止一个以上的 运行ning 进程,您将不得不稍微修改一下代码。
您可以使用 Class 对象来包含进程 ID、进程名称(最终)和一个顺序值来维护对每个进程的引用 运行.
为此使用 List(Of [Class])
您可能还需要修改 StartProcess() 方法以传递控件引用(不同进程输出结果的控件)。
代码实际上只需很少的修改即可实现。