DOBON.NETプログラミング道掲示板

No34645 の記事


■34645 / )  Re[2]: VB.net非同期処理でtextboxに出力したい
□投稿者/ 魔界の仮面弁士 大御所(1315回)-(2021/02/12(Fri) 11:47:14)
  • アイコン
    No34644に追記(魔界の仮面弁士の記事)
    > ただし、標準出力された内容の末尾が改行で無いと
    > OutputDataReceived イベントが発生しない点にご注意ください。
    
    Process.OutputDataReceived イベントの代わりに
    StandardOutput.ReadAsync メソッドを使うようにしてみました。
    
    これなら「PAUSE」や「TIME」にも対応できるかと思います。
    
    
    Public Class Form1
        Private proc As Process
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            If Me.components Is Nothing Then
                Me.components = New System.ComponentModel.Container()
            End If
            Button1.Text = "開始"
            Button2.Text = "標準入力を渡す"
            Button2.Enabled = False
            'コマンド
            TextBox1.Text = Environment.GetEnvironmentVariable("ComSpec")
            '引数
            TextBox2.Text = ""
            '標準入力の内容
            TextBox3.Text = "DIR /D ""C:\Program Files (x86)\"""
            '標準出力 & 標準エラー出力
            RichTextBox1.ReadOnly = True
            RichTextBox1.BackColor = Color.Black
            RichTextBox1.ForeColor = Color.White
            RichTextBox1.ScrollBars = RichTextBoxScrollBars.Both
            RichTextBox1.WordWrap = False
            RichTextBox1.HideSelection = False
        End Sub
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Button1.Enabled = False
            TextBox1.ReadOnly = True
            TextBox2.ReadOnly = True
            RichTextBox1.Clear()
            Button2.Enabled = True
            proc = Process.Start(New ProcessStartInfo(TextBox1.Text, TextBox2.Text) With
            {
                .UseShellExecute = False,
                .CreateNoWindow = True,
                .RedirectStandardInput = True,
                .RedirectStandardOutput = True,
                .RedirectStandardError = True
            })
            Me.components.Add(proc)
            Await Task.WhenAll(
                ConsumeOutput(proc.StandardOutput, False),
                ConsumeOutput(proc.StandardError, True),
                Task.Run(AddressOf proc.WaitForExit)
            )
            proc.Close()
            Me.components.Remove(proc)
            TextBox1.ReadOnly = False
            TextBox2.ReadOnly = False
            Button2.Enabled = False
            Button1.Enabled = True
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            If proc IsNot Nothing Then
                proc.StandardInput.Write(TextBox3.Text & vbLf)
            Else
                Debug.WriteLine("既に閉じられている")
            End If
        End Sub
        Private Async Function ConsumeOutput(reader As System.IO.TextReader, isError As Boolean) As Task
            Dim buffer(2047) As Char
            Dim length As Integer = Await reader.ReadAsync(buffer, 0, buffer.Length)
            Dim foreColor = If(isError, Color.Yellow, Color.White)
            Dim backColor = If(isError, Color.Red, Color.Empty)
            While length > 0
                Dim message As New String(buffer, 0, length)
                Invoke(
                    New MethodInvoker(
                       Sub()
                           Dim pos = RichTextBox1.TextLength
                           RichTextBox1.Select(pos, 0)
                           RichTextBox1.SelectedText = If(message, "")
                           RichTextBox1.Select(pos, length)
                           RichTextBox1.SelectionColor = foreColor
                           RichTextBox1.SelectionBackColor = backColor
                           RichTextBox1.SelectionStart = RichTextBox1.TextLength
                       End Sub
                    )
                )
                length = Await reader.ReadAsync(buffer, 0, buffer.Length)
            End While
        End Function
    End Class

違反を報告
返信 削除キー/


Mode/  Pass/


- Child Tree -