コマンドライン プロセスを実行し、そのプロセスがまだ実行されている間に出力を取得するにはどうすればよいですか?
つまり、独自のプログレスバーを使用して CLI プロセスを実行することです。実行可能ファイル自体が操作を完了するのに長い時間がかかるため、独自のプロセスからその進行状況情報を取得して、アプリケーションで進行状況を表示したいと考えています。プロセスが終了するまで進行状況を表示するための情報はありません。
コンソール アプリではなく、WindowsForm プロジェクトで作業しています。
FFMPEG.exe (x64) を使用して同じことを試みましたが、FFMPEG の実行中に「進行状況」を読み取ることができます。FFMPEG から進行状況を選択して、必要なことを行うことができますが、この実行可能ファイルではできませんそれが可能かどうかはわかりません。
プログラムは「dbPowerAmp CoreConverter」で、音楽コンバーターです。出力を読み取るには、出力エンコーディングをUnicodeに設定する必要があるため、プログラムはすべての出力をUnicodeエンコーディングで送信すると思います。
...その他の問題は、Unicode を使用してもこのプロセスの StandardError 出力を読み取る方法が見つからないことです。
アプリケーションは次のとおりです: http://www.dbpoweramp.com/install/dMC-R14.4-Ref-Trial.exe
以下は、CMD から直接起動されたプログラムの出力例です。
(私が必要とするのは、プロセスの実行中にプログレスバーの「*」アスタリスク文字の量を選択して、アプリケーションでもそのパーセンテージを計算して表示することです)
そして、ここに私のコードがあります:
Private Shared CoreConverter As New Process()
Private Shared CoreConverter_Info As New ProcessStartInfo() With { _
.CreateNoWindow = True, _
.UseShellExecute = False, _
.RedirectStandardOutput = True, _
.RedirectStandardError = True _
}
Private Shared Sub Run_CoreConverter()
' Just for testing CMD Unicode output:
'
' CoreConverter_Info.FileName = "cmd"
' CoreConverter_Info.Arguments = "/U /C C:\CoreConverter.exe " & CoreConverter_Info.Arguments
CoreConverter_Info.FileName = "C:\CoreConverter.exe"
CoreConverter_Info.Arguments = String.Format("-infile=""{0}"" -outfile=""{1}"" -convert_to=""mp3 (Lame)""" ..., blah blah blah)
CoreConverter_Info.StandardErrorEncoding = System.Text.Encoding.Unicode
CoreConverter_Info.StandardOutputEncoding = System.Text.Encoding.Unicode
CoreConverter.StartInfo = CoreConverter_Info
CoreConverter.EnableRaisingEvents = True
CoreConverter.Start()
CoreConverter.WaitForExit()
Dim readerStdOut As IO.StreamReader = CoreConverter.StandardOutput
' This part works with FFMPEG executable but not with Coreconverter.exe,
' What I mean is that the msgbox is displayed when CoreConverter.exe finishes :(
' but with FFMPEG I can read the output while FFMPEG still running.
While CoreConverter.StandardOutput.EndOfStream = True
MsgBox(CoreConverter.StandardOutput.ReadLine)
End While
If CoreConverter.ExitCode <> 0 Then
' Throw New Exception(CoreConverter.StandardError.ReadToEnd)
' No way to read the ErrorOutput...
MessageBox.Show(CoreConverter.StandardError.ReadToEnd, "CoreConverter", MessageBoxButtons.OK, MessageBoxIcon.Error)
MessageBox.Show(CoreConverter.StandardOutput.ReadToEnd, "CoreConverter", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Sub
アップデート:
本当に私はとても絶望的です、私の意図はすべて壮大な失敗です、私は自分のスキルができることをすべて試しました(しかしそれはそれほど多くはありません).
メインスレッドから出力を取得しようとしているときにマルチスレッドを使用して別のスレッドでプロセスを実行しても、プロセスが終了するまでプロセス出力を取得しようとすることはできません。
ただ、私は毎日何時間も無駄にしているというクレイジーなことです.COMオブジェクトを作成することはできるかもしれないと私に言う人もいます.COMオブジェクトを作成する方法を学ぶのに何ヶ月も費やしたくありません.コンソールからいくつかの文字を選択するには、その月の学習は私の人生でこれ以上何の役にも立ちません。単純に、もっと基本的なものが必要です。バッファコンソールを読むというアイデアはうまくいくかもしれませんが、確かにそうではありませんプロセスが終了するまでバッファを読み取ることができるようにします。
そう。このいまいましいプロセスで何ができますか?
私自身の絶望的な言葉を言うために私の質問を更新するだけでなく、私が試したマルチスレッドのものをここに貼り付けます。
...私が言ったように、プロセスがまだ実行されている間に出力を読み取ろうとすることはできず、エラー出力は、プロセスが終了しても(もちろん意図的なエラーで)読み取れません(文字列は常に空です)。 .
Public Shared error_output As String
Public Shared standard_output As String
Public Shared active As Boolean = False ' CoreConverter Thread is active?
Public Shared MyThread As Threading.Thread = New Threading.Thread(AddressOf Run_CoreConverter)
Public Shared Sub Convert_To_MP3(ByVal In_File As String, _
' blah blah blah
'Run_CoreConverter()
MyThread = New Threading.Thread(AddressOf Run_CoreConverter)
' MyThread.IsBackground = True
active = True
MyThread.Start()
Get_Output()
End Sub
Public Shared Sub Get_Output()
While active ' While Coreconverter.exe is runing...
Try
If Not CoreConverter.HasExited Then
MsgBox(CoreConverter.StandardOutput.ReadToEnd) ' This will not be displayed until process has exited...
End If
Catch ex As Exception
End Try
If error_output IsNot Nothing Then
MsgBox(error_output) ' This will not be displayed until process has exited...
End If
If standard_output IsNot Nothing Then
MsgBox(standard_output) ' This will not be displayed until process has exited...
End If
End While
MsgBox("end active")
End Sub
Public Shared Sub Run_CoreConverter()
CoreConverter_Info.FileName = CoreConverter_Location
CoreConverter_Info.StandardErrorEncoding = System.Text.Encoding.Unicode
CoreConverter_Info.StandardOutputEncoding = System.Text.Encoding.Unicode
CoreConverter.StartInfo = CoreConverter_Info
CoreConverter.EnableRaisingEvents = False
CoreConverter.Start()
' CoreConverter.WaitForExit()
' Threading.Thread.Sleep(2000)
' For x As Integer = 0 To 99999999
error_output = CoreConverter.StandardError.ReadToEnd
standard_output = CoreConverter.StandardOutput.ReadToEnd
' Next
If CoreConverter.ExitCode <> 0 Then
Throw New Exception(CoreConverter.StandardError.ReadToEnd)
MessageBox.Show(CoreConverter.StandardError.ReadToEnd, "CoreConverter", MessageBoxButtons.OK, MessageBoxIcon.Error)
MessageBox.Show(CoreConverter.StandardOutput.ReadToEnd, "CoreConverter", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
CoreConverter.Close()
active = False
End Sub