0

私は他の場所でも同様の質問をしましたが、おそらく正しい方法で質問しなかったか、十分に明確ではなかったので、もう一度質問します。

これは私が取得したい場所です:

  1. Windowsコマンドプロンプトを開く
  2. dosコマンドを使用してDOSアプリケーションを実行します
  3. dosボックスに表示されている返されたテキストを読み、Windowsフォームのテキストボックスに表示します。これは定期的に(たとえば、毎秒)繰り返す必要があり、DOSボックスを閉じないでください。

私はProcessコマンドとStartInfoコマンドを使用しようと円を描いて回っていますが、それらはアプリケーションを実行し、すぐにプロセスを閉じるだけです。dosボックスを開いたままにして、dosアプリケーションによって追加された新しいテキストを読み続ける必要があります。私も私の問題に答えているように見えるこのスレッドに出くわしました、しかしそれはC#であり、私はそれを変換することができませんでした:

Windowsコマンドプロンプト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ボックスだけです。カメラのプレビューとQRコードの検出を確認できるため、zbarcamアプリケーションは正常に実行されますが_commandExecutor_OutputRead、DOSボックスを閉じない限り、テキストがDOSボックスに表示されず、subがトリガーされません。

4

2 に答える 2

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
于 2012-07-16T14:19:18.730 に答える
2

これらのコンバーターは通常、イベントに関しては失敗します。


そのコードの直接翻訳は次のようになります。

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プロパティではなく、イベントです。

イベントをサブスクライブするには、C#を使用event += handlerし、VB.NETを使用しますAddHandler event, AddressOf handler

于 2012-07-16T14:04:06.223 に答える