C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

コマンドプロンプトで逐次的にデータを取得する方法

[トピック内 26 記事 (1 - 20 表示)]  << 0 | 1 >>

■95265 / inTopicNo.1)  コマンドプロンプトで逐次的にデータを取得する方法
  
□投稿者/ aaap (1回)-(2020/07/09(Thu) 20:28:43)

分類:[.NET 全般] 

2020/07/09(Thu) 20:31:02 編集(投稿者)

FFmpegというCUIソフトを使っていて、
コマンドプロンプトでコードを実行した後に
非同期で逐次的にエラー出力を取得したいのですが、

https://dobon.net/vb/dotnet/process/standardoutput.html

ここに書いてある
方法で取得することはできました。

しかし、p.StartInfo.UseShellExecute = False
のところをTrueにしないと、コマンドプロンプト上には結果が表示されなくなります。

しかし、Trueにするには、
p.StartInfo.RedirectStandardErrorをFalseにする必要があります

出力を取得しつつ、
コマンドプロンプトウインドウには結果を表示するにはどのようにすれば良いですか?




引用返信 編集キー/
■95266 / inTopicNo.2)  Re[1]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ Hongliang (1058回)-(2020/07/09(Thu) 21:25:20)
もう1つコンソールアプリを作成し、
そのコンソールアプリでffmpegを実行して標準エラーをリダイレクトし、
取得結果を自分の標準エラーに再出力すると同時に
名前付きパイプでも流すようにする。

元々作っていたアプリは、
名前付きパイプを作成しておいて、
リダイレクトなしで上記コンソールアプリを起動し、
名前付きパイプで出力を受け取る。

という方法などどうでしょうか。
引用返信 編集キー/
■95267 / inTopicNo.3)  Re[2]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ 774RR (805回)-(2020/07/09(Thu) 21:39:13)
tee ってのが多分やりたいことを実現してると思う

引用返信 編集キー/
■95268 / inTopicNo.4)  Re[3]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (2回)-(2020/07/09(Thu) 22:22:25)
> もう1つコンソールアプリを作成し、
> そのコンソールアプリでffmpegを実行して標準エラーをリダイレクトし、
> 取得結果を自分の標準エラーに再出力すると同時に
> 名前付きパイプでも流すようにする。

> 元々作っていたアプリは、
> 名前付きパイプを作成しておいて、
> リダイレクトなしで上記コンソールアプリを起動し、
> 名前付きパイプで出力を受け取る。

ありがとうございます。

しかし、具体的にどうすれば良いか分かりません
コードを示していただけないでしょうか?


> tee ってのが多分やりたいことを実現してると思う

なんかできそうな気もするのですが
どうすれば良いか分かりません
ご助言いただけないでしょうか?


引用返信 編集キー/
■95269 / inTopicNo.5)  Re[4]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ Hongliang (1059回)-(2020/07/09(Thu) 23:52:45)
> コードを示していただけないでしょうか?

掲示板の十数行で書けるようなものでもないので残念ながら。
名前付きパイプ以外は特に新しい概念はないはずですが。
引用返信 編集キー/
■95270 / inTopicNo.6)  Re[5]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ 774RR (806回)-(2020/07/10(Fri) 08:58:21)
https://ja.stackoverflow.com/questions/30142
とかでもいけるかも。

tee は標準では入っていないので cygwin をインストールする必要があるっす。
でも cygwin のパスの表記方法と ffmpeg のパスの表記方法が異なるので、慣れていないと混乱の元
powershell なほうが簡単かもしれないっす。

ffmpeg -i c:\mp4\source.mp4 c:\mp4\output.mp4 2>&1 | tee /cygdrive/c/mp4/convert.log


引用返信 編集キー/
■95274 / inTopicNo.7)  Re[6]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (4回)-(2020/07/10(Fri) 12:40:06)
うーん、やはり同時に表示するのは難しそうですね。

代替案として、やはりフォーム上にだけコードを表示することを考えています。

FFmepgはキーボードのQキーを押すことでエンコードを停止させることができるのですが、
プログラム上からコマンドラインプログラムにキーコードを送るにはどのようにすれば良いですか?

引用返信 編集キー/
■95276 / inTopicNo.8)  Re[7]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (1回)-(2020/07/10(Fri) 20:43:17)
私もFFmpegで実行結果を取得するShellプログラムを作って現在使用しています。
FFmpegの場合、実行の経過をエラー出力で画面に表示していますので
私の場合ですがエラー実行結果を非同期で実行して別フォームを表示するようにしています。
ソースがあるんですが、長いのとライブラリ化してVBAで使用できるようにしてしまっているので…
必要ならソースあげましょうか?(vb.net2017版)

引用返信 編集キー/
■95277 / inTopicNo.9)  Re[8]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (2回)-(2020/07/10(Fri) 20:50:09)
あとFFmpegの場合、複数同時実行してもあまり早くなりませんよ。
(GPUを最大限に使おうとするのと、ファイル読み書きの影響で)


引用返信 編集キー/
■95278 / inTopicNo.10)  Re[9]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (5回)-(2020/07/10(Fri) 21:22:53)
No95277 (くまくま さん) に返信

ありがとうございます。
エラー出力の取得の部分は自作プログラムでできているので結構です。

ただ、エンコードを途中で終了させたい場合、
コマンドライン上でQキーを押す必要がありますが、
これをVBのコードから実行するにはどうすれば良いですか?
検索しても情報は見つかりませんでした。

引用返信 編集キー/
■95279 / inTopicNo.11)  Re[10]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (3回)-(2020/07/10(Fri) 21:40:05)
2020/07/10(Fri) 21:51:25 編集(投稿者)
2020/07/10(Fri) 21:50:03 編集(投稿者)

<pre><pre>shell実行を以下として
Private _proc As System.Diagnostics.Process

_proc = New System.Diagnostics.Process()
Dim psi As New System.Diagnostics.ProcessStartInfo()

psi.FileName = "ファイルパス"
psi.Arguments = "実行コマンド"
psi.RedirectStandardError = True
psi.UseShellExecute = False
_proc.StartInfo = psi

'----- 実行
Call _proc.Start()


shellの実行を停止
Try
_proc.Kill()
_proc.WaitForExit()
_proc.Close()
Catch ex As System.Exception
End Try

これでいいかな?</pre></pre>
引用返信 編集キー/
■95280 / inTopicNo.12)  Re[11]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (4回)-(2020/07/10(Fri) 21:48:49)
それか
shell実行時
    psi.RedirectStandardInput = True
として

Try
    If _proc.StandardInput.BaseStream.CanWrite Then
        _proc.StandardInput.WriteLine("Q")
    End If
Catch ex As System.Exception
End Try
※これで止まるかは不明

引用返信 編集キー/
■95281 / inTopicNo.13)  Re[12]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (6回)-(2020/07/10(Fri) 22:19:31)
ありがとうございます。
_proc.Kill()

というように強制的に終了させてしまうと、
途中までエンコードしていても再生できないファイルになってしまいます。
_proc.StandardInput.WriteLine("Q")
はいけそうな気がしたのですが、
_proc.StandardInput.BaseStream.CanWrite
のところでエラーが出て実行できませんでした、

https://dobon.net/vb/dotnet/process/standardoutput.html

このページを見ると
p.WaitForExit()
の前に実行する必要があるのではないでしょうか?

引用返信 編集キー/
■95282 / inTopicNo.14)  Re[13]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (8回)-(2020/07/10(Fri) 22:27:58)

p.Kill()
p.WaitForExit()
p.Close()


こちらも試してみましたが、
コマンドラインからエラー出力が送られてくるのは止まったのですが、
FFmpegだけがなぜかバックグラウンドで動き続けてしまうのですが。

コマンドプロンプトウインドウを手動で消さないと
FFmpegが停止してくれません

引用返信 編集キー/
■95284 / inTopicNo.15)  Re[14]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (6回)-(2020/07/10(Fri) 22:34:42)
No95282 (aaap さん) に返信
>
> p.Kill()
> p.WaitForExit()
> p.Close()
>
>
> こちらも試してみましたが、
> コマンドラインからエラー出力が送られてくるのは止まったのですが、
> FFmpegだけがなぜかバックグラウンドで動き続けてしまうのですが。
>
> コマンドプロンプトウインドウを手動で消さないと
> FFmpegが停止してくれません
>
こちらでは停止しているのですが…
ちょっと動作確認してから再度書き込みますね
引用返信 編集キー/
■95285 / inTopicNo.16)  Re[15]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (7回)-(2020/07/10(Fri) 23:12:48)
2020/07/10(Fri) 23:13:43 編集(投稿者)

No95284 (くまくま さん) に返信
> ■No95282 (aaap さん) に返信
>>
>> p.Kill()
>> p.WaitForExit()
>> p.Close()
>>
>>
>>こちらも試してみましたが、
>>コマンドラインからエラー出力が送られてくるのは止まったのですが、
>>FFmpegだけがなぜかバックグラウンドで動き続けてしまうのですが。
>>
>>コマンドプロンプトウインドウを手動で消さないと
>>FFmpegが停止してくれません
>>
> こちらでは停止しているのですが…
> ちょっと動作確認してから再度書き込みますね

使用バージョン
ffmpeg version git-2019-11-20-d73f062
コマンド
"ffmpeg.exe" -c copy "c:\test.mp4" -i "c:\Test.avi"
変換前aviファイル 3GB(30分)
変換後mp4ファイル 1.8GB

ffmpeg実行後一定カウント(15分前後)で
Try
_proc.Kill()
_proc.WaitForExit()
_proc.Close()
Catch ex As System.Exception
End Try
を実行
・エラー出力の停止を確認
・ファイルサイズの更新を確認
・ffmpegのプロセスを確認
すべて停止している事を確認
これを10回カウント位置を変更して確認

…で停止してるんだけど?
Catchされてるとかないよね?
※_proc.StandardInput.WriteLine("Q")はダメでした

引用返信 編集キー/
■95286 / inTopicNo.17)  Re[16]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (8回)-(2020/07/11(Sat) 00:07:25)
>_proc.Kill()
>
>というように強制的に終了させてしまうと、
>途中までエンコードしていても再生できないファイルになってしまいます。
ごめんなさい見落としていました。
aaapさんがどんな変換を求めているかわかりませんが、大体の動画ファイルは途中でエンコードを止めれば変換エラーのファイルになります。
FFmpeg のコマンドで 「-ss 00:00:00」「-t 00:00:00」で時間指定できますので、もし一部分の切り出しだったらそちらをお勧めします。
(もちろん複数ファイルの結合もできます)
引用返信 編集キー/
■95287 / inTopicNo.18)  Re[17]: コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ くまくま (9回)-(2020/07/11(Sat) 00:20:22)
誤り
>_proc.StandardInput.WriteLine("Q")
正しくは
_proc.StandardInput.WriteLine("q")
にて停止を確認。mp4への変換では再生可能でした。
ただし変換にもよりますが、どうしても停止まで時間がかかります。
即応答ではないので注意して下さい。
引用返信 編集キー/
■95289 / inTopicNo.19)  コマンドプロンプトで逐次的にデータを取得する方法
□投稿者/ aaap (9回)-(2020/07/11(Sat) 10:27:05)
2020/07/11(Sat) 10:33:15 編集(投稿者)
2020/07/11(Sat) 10:28:07 編集(投稿者)

<pre><pre>ありがとうございます。

少しはしょっていますが、コードは以下のような流れになっています。

仰る通り、
_proc.StandardInput.WriteLine("q")
に変更することで、プログラムを停止させることができるようになりました。
しかし、再度、プログラムを実行しようとすると

p.BeginErrorReadLine()


追加情報:非同期読み取り操作はストリーム上で既に開始されました。

というエラーが出てしまい、先に進みません。
と思ったのですが、

p = New System.Diagnostics.Process()

を最後に入れると、うまく再実行できるようになりました。




p.Kill()
p.WaitForExit()
p.Close()

の方も再度試してみましたが、上記で述べたように、
System.Diagnostics.Process()は停止するものの、
コマンドプロンプトは停止せず、FFmpegはバックグラウンドに残ってしまいます。

Catchもされていないようです。

一応、Qキーの方でうまくはいっているのですが
二つ目の方法がうまくいかないのは
何が原因でしょうか?



Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

バックグラウンドプロセス呼び出し

End Sub


Public Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

StopBool = True

End Sub




Public Sub バックグラウンドプロセス




p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec")


p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardError = True
p.StartInfo.RedirectStandardInput = True


AddHandler p.ErrorDataReceived, AddressOf p_OutputDataReceived


p.StartInfo.CreateNoWindow = False
p.StartInfo.Arguments = "/c ffmpeg xxxxx"

p.Start()

p.BeginErrorReadLine()

p.WaitForExit()

p.Close()


End Sub



  Public p As New System.Diagnostics.Process()
 
Public StopBool As Boolean = False



Private Sub p_OutputDataReceived(sender As Object, e As System.Diagnostics.DataReceivedEventArgs)


If StopBool = True Then


Dim method = 1

If method = 0 Then

Try
If p.StandardInput.BaseStream.CanWrite Then
p.StandardInput.WriteLine("q")

End If
Catch ex As System.Exception
End Try


Else


Try

p.Kill()
p.WaitForExit()
p.Close()
Catch ex As System.Exception

Dim hhh = 34

End Try



End If




End If
コードをテキストボックスに表示

End Sub</pre></pre>
引用返信 編集キー/
■95290 / inTopicNo.20)  Re[19]: コマンドプロンプトで逐次的にデータを取得する方法
 
□投稿者/ くまくま (11回)-(2020/07/11(Sat) 11:46:41)
No95289 (aaap さん) に返信
>プログラムを停止させることができるようになりました。
>しかし、再度、プログラムを実行しようとすると
条件が増えているよ...
再度整理してみましょう。
1.FFmpegをvb.net上から実行したい。
2.FFmpeg実行経過をshellのエラー出力から随時取得したい。
3.FFmpegが実行途中でも中止できるようにしたい。
4.FFmpegが中止された際出力されたファイルは再生できる事。
でよいのかな?
それとも
5.FFmpegの処理を一時停止もしたい。
も含むという事かな?

>p.Kill()
実行したプロセスを強制終了する。
>p.WaitForExit()
実行したプロセスが終了するまで待機する。
>p.Close()
プロセスを開放する。

まずバックグラウンドプロセスで
p.WaitForExit()
p.Close()
が入っているのでp_OutputDataReceivedでの
p.WaitForExit()
p.Close()
は不要になります。

またp_OutputDataReceivedでのボタン判定はエラー出力がない場合処理判定できません。
(FFmpegのエラー出力タイミングはスペックが低いマシンだと数十秒かかります。)
p.WaitForExit()で止めるのではなくループでp.HasExitedを確認
(System.Windows.Forms.Application.DoEvents()とSystem.Threading.Thread.Sleep()で調整が必要)

>p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
>p.StartInfo.Arguments = "/c ffmpeg xxxxx"
これだとcmd.exeからffmpegを実行している事になるので

p.StartInfo.FileName = "FFmpegのファイルパス"
(パスが通っているので p.StartInfo.FileName = "ffmpeg.exe" でOK)
p.StartInfo.Arguments = "実行コマンド"
(p.StartInfo.Arguments = "xxxxx")
これでFFmpegを実行できます。

>p.StandardInput.WriteLine("q")
コマンドプロンプトでqキーを入力しているので
ffmpeg.exeは終了してもcmd.exeは終了していないのでは?

>追加情報:非同期読み取り操作はストリーム上で既に開始されました。
pがcloseしてない状態で出力が残っている場合エラーになります。
p.CancelOutputRead()
p.CancelErrorRead()
を実行するか出力をすべて読み切って下さい。

やっぱりソースいる?
「百聞は一見にしかず」じゃないけど実際動作しているソースを見て
ステップ実行などでソースを解釈して自分のソースを書き直したほうが早いと思うよ
引用返信 編集キー/

このトピックをツリーで一括表示

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -