使用VB.net读取和写入命令提示符控制台

时间:2012-07-16 13:05:44

标签: windows vb.net timer command-prompt

我在其他地方问了一个类似的问题,但也许我没有问正确的方法,或者我不够清楚,所以我再问一次。

这是我想要的地方:

  1. 打开Windows命令提示符
  2. 通过dos命令运行DOS应用程序
  3. 读取dos框中显示的返回文本,并将其显示在Windows窗体的文本框中。这需要定期重复(例如,每秒),并且不应关闭dos框。
  4. 我一直在试图使用Process和StartInfo命令,但它们只运行应用程序并立即关闭进程。我需要保持dos框打开并继续读取dos应用程序添加到其中的任何新文本。我也遇到了这个似乎可以解决我的问题的线程,但它是在C#中我无法转换它:

    Read Windows Command Prompt STDOUT

    我确实进入了打开命令提示符并启动应用程序的部分,但我不知道如何读取它不时地返回到dos框控制台的数据。我想不断检查变化,以便我可以对它们采取行动,也许使用定时器控制。

    请帮忙。

    谢谢!

    我运行了由Stevedog友情提供的代码并使用它:

      Private WithEvents _commandExecutor As New CommandExecutor()
    
      Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        _commandExecutor.Execute("c:\progra~2\zbar\bin\zbarcam.exe", "")
      End Sub
    
      Private Sub _commandExecutor_OutputRead(ByVal output As String) Handles _commandExecutor.OutputRead
        txtResult.Text = output
      End Sub
    

    但我得到的只是空白的dos box。 zbarcam应用程序运行正常,因为我可以看到相机预览,我也可以看到它检测QR码,但文本没有显示在dos框中,_commandExecutor_OutputRead sub没有被触发,除非我关闭DOS框。

2 个答案:

答案 0 :(得分:5)

C#示例很糟糕,因为它没有显示如何实际读取标准输出流。创建一个这样的方法:

Public Function ExecuteCommand(ByVal filePath As String, ByVal arguments As String) As String
    Dim p As Process
    p = New Process()
    p.StartInfo.FileName = filePath
    p.StartInfo.UseShellExecute = False
    p.StartInfo.RedirectStandardInput = True
    p.StartInfo.RedirectStandardOutput = True
    p.Start()
    p.WaitForExit()
    Return p.StandardOutput.ReadToEnd()
End Function

然后你可以这样称呼它:

Dim output As String = ExecuteCommand("mycommand.exe", "")

当然这会进行同步通话。如果你想让它以异步方式调用命令行,只是在事件完成时引发一个事件,那也是可能的,但是需要更多的编码。

如果你想以异步方式进行,并且只是在固定的时间间隔内定期检查更多的输出,例如,这是一个简单的例子:

Public Class CommandExecutor
    Implements IDisposable

    Public Event OutputRead(ByVal output As String)

    Private WithEvents _process As Process

    Public Sub Execute(ByVal filePath As String, ByVal arguments As String)
        If _process IsNot Nothing Then
            Throw New Exception("Already watching process")
        End If
        _process = New Process()
        _process.StartInfo.FileName = filePath
        _process.StartInfo.UseShellExecute = False
        _process.StartInfo.RedirectStandardInput = True
        _process.StartInfo.RedirectStandardOutput = True
        _process.Start()
        _process.BeginOutputReadLine()
    End Sub

    Private Sub _process_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles _process.OutputDataReceived
        If _process.HasExited Then
            _process.Dispose()
            _process = Nothing
        End If
        RaiseEvent OutputRead(e.Data)
    End Sub

    Private disposedValue As Boolean = False
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                If _process IsNot Nothing Then
                    _process.Kill()
                    _process.Dispose()
                    _process = Nothing
                End If
            End If
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
End Class

然后你可以像这样使用它:

Public Class Form1
    Private WithEvents _commandExecutor As New CommandExecutor()

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        _commandExecutor.Execute("D:\Sandbox\SandboxSolution\ConsoleCs\bin\Debug\ConsoleCs.exe", "")
    End Sub

    Private Sub _commandExecutor_OutputRead(ByVal output As String) Handles _commandExecutor.OutputRead
        Me.Invoke(New processCommandOutputDelegate(AddressOf processCommandOutput), output)
    End Sub

    Private Delegate Sub processCommandOutputDelegate(ByVal output As String)
    Private Sub processCommandOutput(ByVal output As String)
        TextBox1.Text = output
    End Sub

    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        _commandExecutor.Dispose()
    End Sub
End Class

答案 1 :(得分:2)

这些转换器通常在事件发生时失败。


that code的直接翻译如下:

Dim proc as Process

Sub RunApp
    proc = new Process()
    proc.StartInfo.FileName = "your_app.exe"
    proc.StartInfo.Arguments = ""
    proc.StartInfo.UseShellExecute = false
    proc.StartInfo.RedirectStandardInput = true
    proc.StartInfo.RedirectStandardOutput = true
    AddHandler proc.OutputDataReceived, AddressOf InterProcOutputHandler
    proc.Start()
    proc.WaitForExit()
End Sub

Sub InterProcOutputHandler(sendingProcess as object, outLine as DataReceivedEventArgs)
    'Read data here

    'Send command if necessary
    proc.StandardInput.WriteLine("your_command")
End Sub

proc.OutputDataReceived不是属性,而是event

要订阅活动,请C# event += handler使用VB.NET,而AddHandler event, AddressOf handler使用{{1}}。