如何在Visual Basic中将Shell命令输出到RichTextBox [英] How To Output Shell Command To a RichTextBox In Visual Basic

查看:99
本文介绍了如何在Visual Basic中将Shell命令输出到RichTextBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这整个星期我一直在苦苦挣扎,所以我希望这里的专家可以帮助我。我有一个绝对必须从带有参数的命令行运行的可执行文件。我想做的是代替启动命令提示符窗口,而是将数据发送到表单上的富文本框。

I've been struggling with this all week so I'm hoping the experts here can help me out. I have an executable that absolutely must be run from the command line with arguments. What I'm trying to do is instead of launching the command prompt window, I'd like to send the data to the rich text box on my form.

如果我设置了一个批处理文件并使用正确的代码运行该批处理文件(以 Process 的身份运行),则此操作没有问题。但是,我希望用户能够在 TextBox 中输入自己的参数,而不是创建批处理文件并对其进行引用。

If I setup a batch file and run the batch file with the correct code (running it as a Process), this works no problem. However, I'd like for the user to be able to enter their own arguments into a TextBox instead of creating a batch file and referencing it.

我只能通过使用Call Shell使此应用程序正确运行。但是,我读到如果使用Call Shell,则无法将数据输出到 RichTextBox ,并且需要将其设置为新的处理。我似乎无法以 Process 的方式运行它。

I can only get this application to run correctly by using Call Shell. However, I read that you can't output the data to a RichTextBox if you're using Call Shell and that it needs to be setup as a new Process. I just can't seem to get this running as a Process.

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

So the question is, is it possible to somehow output the Call Shell data to a RichTextBox control, or is there a way to get this thing to run as a process? The Visual Basic code below will get it to run, but won't output to the RichTextBox. I removed any code that I tried because every try was a failure.

此按钮将启动进程,或者如果 Process 正在运行,它将杀死它。

This button will start the Process, or if the Process is running, it will kill it.

    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

实际结果取决于该程序的实际工作方式。

可能需要进行一些测试s以使其输出正确。

It's quite possible using System.Diagnostics.Process.
The actual result depends on how that program actually works.
It might require some tests to get its output right.

这是一个通用过程,可用于测试可执行文件是否以标准方式运行。

它使用 tracert.exe 并将其结果输出到 RichTextBox 控件中。

This is a generic procedure you can use to test if your executable behaves in a standard way.
It's using tracert.exe and ouputs its results in a RichTextBox control.

请注意, Process.Start()初始化使用 Process.SynchronizingObject()设置为 RichTextBox 控制父表单,以避免 InvokeRequired 。但是,如果您不想使用Synch对象,则可以使用 MethodInvoker 委托。

Note that the Process.Start() initialization uses the 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 delegate.

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

To switch to your executable, subsitute the StartProcess() method parameters as required.

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", "stackoverflow.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


注意

如果需要终止一个正在运行的进程,则必须多修改一些代码。

您可以使用Class对象来包含Process ID,流程名称(最终)和顺序值,以维护对每个流程运行的引用。

使用 List(Of [Class])

您可能还需要修改 StartProcess()方法以传递控件引用(不同进程输出其结果的控件) 。

像这样的代码是,只需很少的修改即可实现。

Note:
If you need to terminate more that one running processes, you'll have to modify the code a bit more.
You could use a Class object to contain the Process Id, the Process Name (eventually) and a sequential value to maintain a reference to each process run.
Use a List(Of [Class]) for this.
You might also need to modify the StartProcess() method to pass a Control reference (the Control where the different processes output their results).
The code, as it is, needs very few modifications to achieve this.

这篇关于如何在Visual Basic中将Shell命令输出到RichTextBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆