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

查看:25
本文介绍了如何在 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.我似乎无法让它作为 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,或者如果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.
实际结果取决于该程序的实际工作方式.
可能需要进行一些测试才能使其输出正确.

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 对象,则无论如何都会处理 Control.Invoke,使用 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:WindowsSystem32	racert.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 对象来包含进程 ID、进程名称(最终)和一个序列值,以维护对每个进程运行的引用.
为此使用 List(Of [Class]).
您可能还需要修改 StartProcess() 方法以传递 Control 引用(不同进程输出其结果的 Control).
代码需要很少的修改才能实现这一点.

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天全站免登陆