【问题标题】:executing ffmpeg.exe from delphi with shellExecute使用 shellExecute 从 delphi 执行 ffmpeg.exe
【发布时间】:2015-02-18 09:55:13
【问题描述】:

我正在尝试从 bmp 图像列表制作视频,当我从命令行ffmpeg -i img%5d.bmp -r 20 -c:v libx264 -preset slow -crf 22 output.mkv 执行时一切正常,但是当我尝试从 delphi 项目执行时,它不起作用。我试过了:

parameters := '-i img%5d.bmp -r 20 -c:v libx264 -preset slow -crf 22  output.mkv';
ShellExecute(0, nil, PChar('c:\videos\ffmpeg.exe'), PChar(parameters), nil, SW_NORMAL); 

我不能使用TProcess,必须使用ShellExecute 请帮我解决这个问题,提前 tnx :)

【问题讨论】:

  • 当您致电ShellExecute 时,您将收获您所播种的东西。它不支持理智的错误处理。使用ShellExecuteEx 并获得正确的错误代码。然后从那里拿走。但是,ShellExecuteEx 仍然是错误的函数。您需要致电CreateProcess 执行此操作正确
  • 我是新手,不知道怎么处理参数和特殊字符:(
  • 我坚持我在评论中所说的话。
  • 当我使用 ShellExecuteEx 时,我得到了太多的实际参数,并且 CreateProcess 中有一些我不理解的参数
  • @hudyboy 只有一种方法可以解释“太多实际参数”。你不理解这些的原因是你像一只无头鸡一样到处乱跑。调用函数并传递太多参数的唯一方法是不阅读文档。如果你不阅读文档,除了失败,你还能指望什么?

标签: delphi ffmpeg shellexecute


【解决方案1】:

这是我使用的一小段代码。我给你这个代码,但希望你不只是复制和粘贴。请仔细阅读以了解它的作用。

David 谈到了 CreateProcess。这是在 Windows 中创建和处理进程的最佳方式。还要注意 WaitForSingleObject。这会导致您的执行在创建进程后返回之前等待 Windows 完成。您当然可以删除等待部分。还要注意创建标志。

它被称为 ExecuteAndWait。当你调用它时,它会创建一个进程并等待它完成:

function ExecuteAndWait(AFilename : String; AParameter : string;
                        ACmdShow : Integer; var AErrorOrExitCode : Cardinal): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  S : String;
begin
  FillChar(StartupInfo,Sizeof(StartupInfo),0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := ACmdShow;
  S := AParameter;
  UniqueString(S);
  if not CreateProcess(PChar(AFilename),PChar(S),nil,nil,False,
                       CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,nil,nil,
                       StartupInfo,ProcessInfo) then
    begin
      Result := False;
      AErrorOrExitCode := GetLastError;
    end
  else
    begin
      Result := True;
      WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
      GetExitCodeProcess(ProcessInfo.hProcess,AErrorOrExitCode);
      CloseHandle(ProcessInfo.hProcess);
      CloseHandle(ProcessInfo.hThread);
    end;
end;

例子:

var
  ErrorOrExitCode : Cardinal;
begin
  If not ExecuteAndWait('c:\windows\regedit.exe','"c:\windows\regedit.exe" "c:\test.reg"',SW_SHOWDEFAULT,ErrorOrExitCode) then
    Showmessage(Inttostr(ErrorOrExitCode));

这里我告诉 regedit 加载一个导出的 reg 文件。注意双引号,还要注意我将可执行文件指定为文件名和参数的一部分。

根据您的需要调整它。

【讨论】:

  • CreateNoWindow 真的是你想要的,让你隐藏控制台。不需要STARTF_USESHOWWINDOW,因为我们正在启动一个控制台应用程序。您的代码泄漏了两个句柄。
  • 没错,但我将此代码作为我用于不同用途的代码。尽管人们希望新手不要研究提供的代码,但人们希望他成为例外并检查可以使用哪些不同的参数。至少这是我所希望的。
  • 另一个问题是CreateProcess的第二个参数可能被修改了。所以你不能传递文字。对于 CreateProcessA,您可以逃脱惩罚,但对于 CreateProcessW 则不然。添加对 UniqueString 的调用。
  • @大卫。据我所知;将 AParameter 字符串复制到 ExecuteAndWait 中的局部变量就足以解决问题,而无需再使用 UniqueString。我说的对吗?
  • 不,你不正确。文字存储在只读存储器中。从一个字符串 var 复制到另一个不会复制有效负载。您需要一个 SetLength、一个字符修改、一个 UniqueString 等来将副本复制到可写内存中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-04
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多