Problem bei Kommandozeile Auslesen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Problem bei Kommandozeile Auslesen

    Hallo liebe Leute,

    ich verzweifle gerade dabei, eine laufende Kommandozeile von FFMPEG auszulesen.
    Eigentlich sollte der Code so funktionieren, ich bekomme jedoch immer die Fehlermeldung:
    "Es wurde bereits ein asynchroner Lesevorgang für diesen Stream gestartet"

    Hier der Code:

    VB.NET-Quellcode

    1. Delegate Sub UpdateTextBoxTextDelegate(text As String)
    2. Dim myProcess As New Process()
    3. Private Sub Startfile()
    4. ListBox1.SetSelected(line, True)
    5. Dim video As String
    6. video = ordner & "\" & ListBox1.Items.Item(line).ToString
    7. pfad = video
    8. Dim reader As System.IO.DirectoryInfo
    9. reader = My.Computer.FileSystem.GetDirectoryInfo(pfad)
    10. game = reader.Parent.Name
    11. twitchgame = game
    12. Dim MyTitle As String = GetTitle(pfad)
    13. titel = MyTitle
    14. Try
    15. AddHandler myProcess.OutputDataReceived, AddressOf ProcessOutputDataReceived
    16. myProcess.StartInfo.FileName = ffmpeg
    17. Dim Parameter As String = "-i " & Chr(34) & pfad & Chr(34) & " -c:v libx264 -f mp4 " & Output
    18. myProcess.StartInfo.Arguments = Parameter
    19. myProcess.StartInfo.UseShellExecute = False
    20. myProcess.StartInfo.RedirectStandardOutput = True
    21. myProcess.StartInfo.CreateNoWindow = True
    22. myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    23. myProcess.Start()
    24. myProcess.BeginOutputReadLine()
    25. Catch er As Exception
    26. MessageBox.Show(er.Message)
    27. End Try
    28. Button1.Enabled = False
    29. Button2.Enabled = True
    30. Timer2.Enabled = True
    31. End Sub
    32. Private Sub UpdateTextBoxText(text As String)
    33. #If DEBUG Then
    34. Debug.WriteLine(text)
    35. #End If
    36. Me.TextBox3.AppendText(text + Environment.NewLine)
    37. End Sub
    38. Private Sub ProcessOutputDataReceived(sender As Object, e As _
    39. DataReceivedEventArgs)
    40. If Not String.IsNullOrEmpty(e.Data) Then
    41. Me.Invoke(New UpdateTextBoxTextDelegate(AddressOf UpdateTextBoxText), New _
    42. Object() {e.Data})
    43. End If
    44. End Sub


    Ich glaub ich seh den Wald vor lauter Bäumen nicht 8|

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Scarala“ ()

    Scarala schrieb:

    ich bekomme jedoch immer die Fehlermeldung
    in welcher Zeile?
    #If DEBUG / #End If kannst Du ersatzlos streichen, das übernimmt Debug... für Dich.
    Kannst Du Dein Snippet so weit abspecken, dass auf keinerlei Controls zugegriffen wird und der Fehler immer noch kommt (das lässt sich leichter nachvollziehen)?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe jetzt die Sub Startfile() gekürzt:

    VB.NET-Quellcode

    1. Private Sub Startfile()
    2. Try
    3. AddHandler myProcess.OutputDataReceived, AddressOf ProcessOutputDataReceived
    4. myProcess.StartInfo.FileName = "C:\Users\boenk-\Desktop\ffmpeg\bin\ffmpeg.exe"
    5. Dim Parameter As String = "-i C:\Users\boenk-\Desktop\ffmpeg\bin\Wildlife.wmv -c:v libx264 -f mp4 C:\Users\boenk-\Desktop\ffmpeg\bin\render.mp4"
    6. myProcess.StartInfo.Arguments = Parameter
    7. myProcess.StartInfo.UseShellExecute = False
    8. myProcess.StartInfo.RedirectStandardOutput = True
    9. myProcess.StartInfo.CreateNoWindow = True
    10. myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    11. myProcess.Start()
    12. myProcess.BeginOutputReadLine()
    13. Catch er As Exception
    14. MessageBox.Show(er.Message)
    15. End Try
    16. End Sub


    Jetzt kommt keine Fehlermeldung, jedoch wird in der Textbox auch kein Text ausgegeben.

    Mit dem Code vom 1. Posting kommt der Fehler in Zeile 26.

    VB.NET-Quellcode

    1. myProcess.BeginOutputReadLine()


    EDIT: Mir fällt gerade auf, die Fehlermeldung kommt erst bei der 2. abgespielten Datei in der Playlist des Programms. Nichts desto trotz erfolgt keine Ausgabe in die Textbox.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Scarala“ ()

    Komisch, genau wie in der MSDN beschrieben.
    Füge mal nach der Zeile

    Scarala schrieb:

    VB.NET-Quellcode

    1. myProcess.Start()
    dies ein:

    VB.NET-Quellcode

    1. myProcess.WaitForInputIdle(500)
    Der wartet (max. 500 ms) bis der Prozess ordentlich läuft.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Scarala schrieb:

    keine grafische Schnittstelle
    Klar.
    Wenn der Prozess keine GUI hat, kannst Du so nicht mit ihm kommunizieren.
    Möglicherweise kannst Du gar nicht mit ihm kommunizieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So, ich bin schon etwas weitergekommen.

    Die Ausgabe der Kommandozeile funktioniert bei der ersten Datei aus der Playlist mit folgendem Code:

    VB.NET-Quellcode

    1. Private WithEvents myProcess As Process = New Process
    2. Private Delegate Sub WriteA(ByVal Text As String)
    3. Private Sub Startfile()
    4. ListBox1.SetSelected(line, True)
    5. Dim video As String
    6. video = ordner & "\" & ListBox1.Items.Item(line).ToString
    7. pfad = video
    8. myProcess.StartInfo.FileName = ffmpeg
    9. Dim Parameter As String = "-re -i " & Chr(34) & pfad & Chr(34) & " -c:v libx264 -f mp4 " & Output
    10. End If
    11. myProcess.StartInfo.Arguments = Parameter
    12. myProcess.StartInfo.UseShellExecute = False
    13. myProcess.StartInfo.RedirectStandardOutput = True
    14. myProcess.StartInfo.RedirectStandardError = True
    15. myProcess.StartInfo.CreateNoWindow = True
    16. myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    17. myProcess.Start()
    18. myProcess.BeginErrorReadLine()
    19. myProcess.BeginOutputReadLine()
    20. Button1.Enabled = False
    21. Button2.Enabled = True
    22. Timer2.Enabled = True
    23. End Sub
    24. Private Sub p_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) Handles myProcess.OutputDataReceived
    25. Me.Invoke(New WriteA(AddressOf Write), e.Data & Environment.NewLine)
    26. End Sub
    27. Private Sub p_ErrorDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) Handles myProcess.ErrorDataReceived
    28. Me.Invoke(New WriteA(AddressOf Write), e.Data & Environment.NewLine)
    29. End Sub
    30. Private Sub Write(ByVal Line As String)
    31. If Not Line.Contains("=") Then
    32. TextBox4.Text &= Line
    33. End If
    34. If Line.Contains("=") Then
    35. If Line.Substring(0, Line.IndexOf("=")) = "frame" Then
    36. TextBox3.Text = Line
    37. End If
    38. End If
    39. If Line.Contains("Error") Then
    40. Button2.PerformClick()
    41. MsgBox("Verbinden fehlgeschlagen!" & vbNewLine & "Fehler in FFMPEG-Einstellungen!")
    42. End If
    43. If Line.Contains("failed to connect socket") Then
    44. Button2.PerformClick()
    45. MsgBox("Verbinden fehlgeschlagen!" & vbNewLine & "Zielserver nicht erreichbar!")
    46. End If
    47. End Sub


    Dabei habe ich festgestellt, das FFMPEG die Kommandozeile über ErrorData und nicht über OutputData rausgibt.

    Jedoch kommt immer noch, sobald er die 2. Datei rendern will die Meldung:

    Quellcode

    1. Es wurde bereits ein asynchroner Lesevorgang für diesen Stream gestartet

    bei dem Befehl

    VB.NET-Quellcode

    1. myProcess.BeginErrorReadLine()

    Scheint als würde der Befehl "myProcess.BeginErrorReadLine()" beim automatischen Beenden von FFMPEg, wenn es fertig ist mit Rendern, nicht automatisch geschlossen.
    habe es auch schon mit einem Timer versucht:

    VB.NET-Quellcode

    1. Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
    2. If myProcess.HasExited = True Then
    3. TextBox3.Clear()
    4. myProcess.close()
    5. End If
    6. End Sub

    Der fehler besteht weiterhin...

    Wenn ich "myProcess.BeginErrorReadLine()" Nur einmalig bei der ersten Datei starte Rendert er alle Dateien wie er soll durch, zeigt mir jedoch nur die Kommandozeile der ersten Datei, danach bleiben die TextBoxen leer.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Scarala“ ()

    Scarala schrieb:

    nur die Kommandozeile der ersten Datei
    Und wenn Du den Prozess für jede Datei neu startest?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das ist ja hier der fall... wenn die erste Datei fertig gerendert ist schließt sich die Kommandozeile von ffmpeg automatisch. Dann schließe ich mit myProcess.close() den Prozess und dann wird die Sub Startfile neu aufgerufen mit der nächsten Datei.

    Ich konnte das Problem lösen.

    VB.NET-Quellcode

    1. ​Private WithEvents myProcess As Process
    2. Private Delegate Sub WriteA(ByVal Text As String)
    3. Private Sub Startfile()
    4. ListBox1.SetSelected(line, True)
    5. Dim video As String
    6. video = ordner & "\" & ListBox1.Items.Item(line).ToString
    7. pfad = video
    8. myProcess = new Process
    9. myProcess.StartInfo.FileName = ffmpeg
    10. Dim Parameter As String = "-re -i " & Chr(34) & pfad & Chr(34) & " -c:v libx264 -f mp4 " & Output
    11. End If
    12. myProcess.StartInfo.Arguments = Parameter
    13. myProcess.StartInfo.UseShellExecute = False
    14. myProcess.StartInfo.RedirectStandardOutput = True
    15. myProcess.StartInfo.RedirectStandardError = True
    16. myProcess.StartInfo.CreateNoWindow = True
    17. myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    18. myProcess.Start()
    19. myProcess.BeginErrorReadLine()
    20. myProcess.BeginOutputReadLine()
    21. Button1.Enabled = False
    22. Button2.Enabled = True
    23. Timer2.Enabled = True
    24. End Sub
    25. Private Sub p_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) Handles myProcess.OutputDataReceived
    26. Me.Invoke(New WriteA(AddressOf Write), e.Data & Environment.NewLine)
    27. End Sub
    28. Private Sub p_ErrorDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) Handles myProcess.ErrorDataReceived
    29. Me.Invoke(New WriteA(AddressOf Write), e.Data & Environment.NewLine)
    30. End Sub
    31. Private Sub Write(ByVal Line As String)
    32. If Not Line.Contains("=") Then
    33. TextBox4.Text &= Line
    34. End If
    35. If Line.Contains("=") Then
    36. If Line.Substring(0, Line.IndexOf("=")) = "frame" Then
    37. TextBox3.Text = Line
    38. End If
    39. End If
    40. If Line.Contains("Error") Then
    41. Button2.PerformClick()
    42. MsgBox("Verbinden fehlgeschlagen!" & vbNewLine & "Fehler in FFMPEG-Einstellungen!")
    43. End If
    44. If Line.Contains("failed to connect socket") Then
    45. Button2.PerformClick()
    46. MsgBox("Verbinden fehlgeschlagen!" & vbNewLine & "Zielserver nicht erreichbar!")
    47. End If
    48. End Sub
    49. Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
    50. If myProcess.HasExited = True Then
    51. TextBox3.Clear()
    52. myProcess.Dispose()
    53. End If
    54. End Sub


    Also die Variable erst im Sub Startfile() als neuen Prozess definiert und dann nach schließen der Konsole mit myProcess.dispose() die Variable wieder komplett geleert.
    Dann wird die Variable bei der 2. Videodatei wieder neu als new Process definiert und es klappt alles wie es soll.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Scarala“ ()

    Scarala schrieb:

    Dann schließe ich mit myProcess.close() den Prozess
    Process sendet ein Excited-Event, das musst Du abonieren, gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!