AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Externe Programme asynchron trotz WaitForSingleObject?
Thema durchsuchen
Ansicht
Themen-Optionen

Externe Programme asynchron trotz WaitForSingleObject?

Ein Thema von Maekkelrajter · begonnen am 1. Mai 2017 · letzter Beitrag vom 18. Mai 2017
Antwort Antwort
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
118 Beiträge
 
Delphi 11 Alexandria
 
#1

Externe Programme asynchron trotz WaitForSingleObject?

  Alt 1. Mai 2017, 12:37
Zur Zeit arbeite ich (mal wieder) an einem Programm, das mit iTunes interagiert. Unter anderem enthält es eine Funktion zur Anonymisierung der von Apple gelieferten M4A - Dateien, die ich auf meinen diversen mobilen Geräten abspielen möchte. Diese Dateien enthalten nämlich im Klartext Name und EMail-Adresse und womöglich noch andere, nicht ohne weiteres erkennbare Daten, die auf meine Identität hinweisen. Ich möchte nämlich vermeiden, dass etwa bei Verlust oder Diebstahl eines solchen Gerätes personalisierte Titel aus meinen Mediatheken in irgendwelchen Tauschbörsen auftauchen. Vielleicht alles nur Paranoia, aber das sollte nicht Gegenstand der Diskussion sein

Zur Bearbeitung der Dateien benutze ich das Kommandozeilenprogramm ffmpeg.exe

Delphi-Quellcode:
Function TGLMainform.CMDExec(cmdline:string):Boolean;
var
  i:Integer;
  s1:string;
  Output : TStringList;
  Errors : TStringList;
begin
  result:= false;
  Output := TStringList.Create;
  Errors := TStringList.Create;
  try
    If GetConsoleOutput(cmdline, Output, Errors) then
    begin
      result:= true;
      Loglist.add(#13#10+cmdline);
      Loglist.AddStrings(output);
      for i:= 0 to Errors.count -1 do
      begin
        s1:= Errors[i];
        If pos('WARN',s1) > 0 then
        begin
          Loglist.add('WARNING: ' + s1);
        end;
      end;
    end;
  finally
    Output.free;
    Errors.free;
  end;
end;


const ffmpg:= '"D:\Externals\ffmpeg\ffmpeg.exe" -loglevel error -i ';


procedure TGLMainform.Anonymize(const sourcefile,cleanfile:string);
  var tempfile:string;
begin
  tempfile:= changefileext(cleanfile,'.aac');
  cmdexec(ffmpg + #34 + sourcefile + #34 + ' -acodec copy ' + #34 + tempfile + #34); // Audiostream extrahieren
  cmdexec(ffmpg + #34 + tempfile + #34 + ' -absf aac_adtstoasc -acodec copy ' + #34 + cleanfile + #34); // Audiostream in leeren MP4 Container
  sysutils.DeleteFile(tempfile);
end;
Die Function cmdexec ruft ihrerseits 'GetConsoleOutput' auf und schreibt die Ausgaben und Errors des aufgerufenen Programmes in ein Logfile;
Anschließend werden ausgewählte, zuvor aus dem Original-File ausgelesene und gesicherte Tags in die neue M4A - Datei zurückgeschrieben. Das Ganze läuft in einer Schleife, in der schonmal mehrere 1000 Dateien verarbeitet werden können.
Im Prinzip funktioniert das alles wie es soll.
Gelegentlich kommt es jedoch vor, dass der zweite Aufruf von ffmpeg einen Fehler 'File not found' zurückgibt. Ich nahm zunächst an, dass das temporäre File tempfile.aac zu diesem Zeitpunkt noch nicht erstellt ist. Versuche (auskommentieren des 'sysutils.DeleteFile') ergaben dann aber, dass die Löschung des tempfiles für den Fehler verantwortlich war. WaitForSingleObject signalisiert also offenbar das Beenden von ffmpeg, bevor der jeweilige Kopiervorgang tatsächlich abgeschlossen ist.
Als Workaround habe ich die Namen der Tempfiles zunächst in einer Stringlist gespeichert und erst am Abschluss der ganzen Aktion in einem Rutsch gelöscht. Bisher klappte das immer fehlerfrei, was natürlich keineswegs garantiert ist. Gerade Kopieraktionen im Netzwerk dauern schon mal etwas länger, sodass die Gefahr besteht, dass zumindest der letzte Aufruf von ffmpeg fehlschlägt. Wie kann man also sicherstellen, dass die Kopieraktionen tatsächlich beendet wurden, bevor die Deletefile - Funktion aufgerufen wird?
Mein Ansatz ist, vor dem zweiten Aufruf von ffmpeg bzw. vor dem Aufrufen von DeleteFile

  While not Fileexists(tempfile) do sleep(100)

einzufügen. Das funktioniert natürlich erstmal, aber das kann auch Zufall sein, weil der Fehler sich nicht zuverlässig reproduzieren läßt

Welche Möglichkeiten gibt es sonst noch??
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
118 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Externe Programme asynchron trotz WaitForSingleObject?

  Alt 18. Mai 2017, 13:50
GetConsoleoutput ist hier im Forum öfter erwähnt bzw. gepostet worden:
http://www.delphipraxis.net/164364-d...-einlesen.html
Deshalb hatte ich auf das Posten des Codes verzichtet.
WaitForSingleObject(ProcessInfo.hProcess, INFINITE) signalisiert offenbar das Beenden von ffmpeg, bevor der eigentliche Kopiervorgang ('-acodec copy') überhaupt begonnen hat.

Für Testzwecke habe habe ich die Warteschleife erweitert und lasse eine Variable hochzählen und, falls > 0, im Logfile eine entsprechende Meldung hinterlegen:
Delphi-Quellcode:
const ffmpg:= '"D:\Externals\ffmpeg\ffmpeg.exe" -loglevel error -i ';


procedure TGLMainform.Anonymize(const sourcefile,cleanfile:string);
  var tempfile: string;
      loopcount: Integer;
begin
  tempfile:= changefileext(cleanfile,'.aac');
  cmdexec(ffmpg + #34 + sourcefile + #34 + ' -acodec copy ' + #34 + tempfile + #34); // Audiostream extrahieren
  cmdexec(ffmpg + #34 + tempfile + #34 + ' -absf aac_adtstoasc -acodec copy ' + #34 + cleanfile + #34); // Audiostream in leeren MP4 Container
  loopcount:= 0;
  While not Fileexists(cleanfile) do // Kopiervorgang tempfile > cleanfile abgeschlossen?
  begin
    sleep(100);
    inc(loopcount);
  end;
  sysutils.DeleteFile(tempfile);
  If loopcount > 0 Then Loglist.add('Durchläufe Warteschleife: ' + inttostr(loopcount));
end;
Bisher wurde noch kein einziges Mal ein Wert > 0 gemeldet, aber das kann, wie schon gesagt, günstigen Umständen geschuldet sein.
Ich suche nach wie vor nach einer 'sauberen' und zuverlässigen Lösung

Geändert von Maekkelrajter (18. Mai 2017 um 14:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz