vb.net - 如何在 Visual Basic 中将 Shell 命令输出到 RichTextBox
问题描述
我整个星期都在努力解决这个问题,所以我希望这里的专家可以帮助我。我有一个绝对必须从带有参数的命令行运行的可执行文件。我想要做的不是启动命令提示符窗口,而是将数据发送到表单上的富文本框。
如果我设置一个批处理文件并使用正确的代码运行批处理文件(将其作为 a 运行Process
),这没有问题。但是,我希望用户能够将自己的参数输入 aTextBox
而不是创建批处理文件并引用它。
我只能通过使用 Call Shell 让这个应用程序正确运行。RichTextBox
但是,我读到如果您使用 Call Shell,则无法将数据输出到 a并且需要将其设置为新的Process
. 我似乎无法让它作为Process
.
所以问题是,是否有可能以某种方式将 Call Shell 数据输出到RichTextBox
控件,或者有没有办法让这个东西作为一个进程运行?下面的 Visual Basic 代码将使其运行,但不会输出到RichTextBox
. 我删除了我尝试过的所有代码,因为每次尝试都是失败的。
此按钮将启动Process
,或者如果Process
正在运行,它将终止它。
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()设置为RichTextBox
控件父窗体来避免InvokeRequired
。但是,如果您不想使用 Synch 对象,Control.Invoke
则无论如何都要使用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", "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、进程名称(最终)和一个顺序值,以维护对每个进程运行的引用。为此
使用 a 。
您可能还需要修改方法以传递 Control 引用(不同进程输出其结果的 Control)。
代码实际上只需要很少的修改就可以实现这一点。List(Of [Class])
StartProcess()
推荐阅读
- jquery - 当我使用 jquery-ui 自动完成在文本区域中键入时,如何在任何位置实现自动完成?
- angular - @ViewChild() 来自另一个组件
- java - Thymeleaf 3 语法迭代列表
- >
- javascript - 如何在javascript中复制标签时增加ID
- flutter - 如何正确管理 Flutter 应用中的全局 textScaleFactor?
- powershell - 如何使用 powershell 命令获取 SCVMM 中可用主机的列表
- node.js - 如何在 macOS(mojave 10.14)上优雅地停止 nodejs 服务器侦听器?
- hibernate - 在应用程序中使用休眠序列作为通用序列
- html - 选项标签禁用属性
- c# - 身份4、程序化登录