CreateProcess : 应用程序路径中的转义空格
Posted
技术标签:
【中文标题】CreateProcess : 应用程序路径中的转义空格【英文标题】:CreateProcess : escape spaces in the application path 【发布时间】:2014-03-10 16:40:33 【问题描述】:我们需要在我的 delphi 应用程序的命令窗口中执行 ffmpeg。
我们找到了使用“ExtractShortPathName”函数保护路径的解决方案。
但在某些计算机上我们无法获得 8.3 路径(HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation 为 2),我们想找到另一种方法来逃避空格。
代码如下:
sParameters := '"C:\Users\[...]\input.wav" -r 12.03 -f image2 -i "C:\Users\[...]\delphilm%d.png" -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre "C:\[...]\libx264-normal.ffpreset" "C:\Users\[...]\export.mp4"';
sCommand := 'C:\Program Files\My application\utils\bin\ffmpeg.exe';
Handle := CreateProcess(nil, PChar('cmd.exe /C '+ProtectPath(sCommand)+' '+sParameters),nil, nil, True, 0, nil, nil, SI, PI);
使用 ProtectPath 功能:
function ProtectPath(sCommand:Widestring):Widestring;
begin
Result := sCommand;
// get the 8.3 path
Result := ExtractShortPathName(sCommand);
// if 8.3 path is not accessible
if(Pos(' ', Result)>0)then begin
//Result := '"'+sCommand+'"'; --> do not work
//Result := StrReplace(sCommand, ' ','" "'); --> do not work
//Result := StrReplace(sCommand, ' ','^ '); --> do not work
//Result := StrReplace(sCommand, ' ','\ '); --> do not work
//Result := StrReplace(sCommand, ' ','\\ '); --> do not work
//Result := StrReplace(sCommand, ' ','/ '); --> do not work
//Result := StrReplace(sCommand, ' ','// '); --> do not work
end;
end;
有什么想法吗?
【问题讨论】:
用正斜杠替换反斜杠。我通常在 C++ 中使用它。仅适用于路径。没有其他的。希望它在这里工作。 OT:我仍然想知道为什么人们倾向于使用cmd.exe /C
。直接执行应用程序不是更容易吗?
正斜杠不起作用。
我们使用cmd.exe来分析ffmpeg过程中的输出。
msdn.microsoft.com/en-us/library/windows/desktop/… cmets 部分指出,如果文件没有短名称,它将失败。好像有不少gotchas
在使用这个功能。某些系统没有某些路径的短名称。
【参考方案1】:
您不需要检索 8.3 文件名。您所要做的就是用一对引号括起一个长路径,如果它包含任何空格字符(就像您已经在使用一些 FFMPEG 参数一样)。然后,完全摆脱cmd.exe
,直接调用ffmpeg.exe
。
sCommand := '"C:\Program Files\My application\utils\bin\ffmpeg.exe"';
sParameters := '"C:\Users\[...]\input.wav" -r 12.03 -f image2 -i "C:\Users\[...]\delphilm%d.png" -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre "C:\[...]\libx264-normal.ffpreset" "C:\Users\[...]\export.mp4"';
Handle := CreateProcess(nil, PChar(sCommand + ' ' + sParameters), nil, nil, True, 0, nil, nil, SI, PI);
如果您想动态引用,请使用(Ansi)QuotedStr()
,例如:
function ProtectParam(sParam: String): String;
begin
if LastDelimiter(' "', sParam) <> 0 then
Result := QuotedStr(sParam)
else
Result := sParam;
end;
FFMPEG := 'C:\Program Files\My application\utils\bin\ffmpeg.exe';
InputFile := 'C:\Users\[...]\input.wav';
PngFile := 'C:\Users\[...]\delphilm%d.png';
PresetFile := 'C:\[...]\libx264-normal.ffpreset';
ExportFile := 'C:\Users\[...]\export.mp4';
sCommand := ProtectParam(FFMPEG) + ' ' + ProtectParam(InputFile) + ' -r 12.03 -f image2 -i ' + ProtectParam(PngFile) + ' -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre ' + ProtectParam(PresetFile) + ' ' + ProtectParam(ExportFile);
Handle := CreateProcess(nil, PChar(sCommand), nil, nil, True, 0, nil, nil, SI, PI);
【讨论】:
【参考方案2】:我看不出有什么真正的理由在这里使用cmd.exe
。它只是增加了一层额外的复杂性,会让你感到痛苦。你是要求cmd.exe
打电话CreateProcess
启动ffmpeg
,那为什么不直接做呢?
也就是说,回避问题的一种廉价而愉快的方法是利用工作目录。将'C:\Program Files\My application\utils\bin'
传递给新进程的工作目录,然后PChar('cmd.exe /C ffmpeg.exe '+sParameters)
就是你所需要的。
【讨论】:
以上是关于CreateProcess : 应用程序路径中的转义空格的主要内容,如果未能解决你的问题,请参考以下文章
无法启动应用程序(CreateProcess 错误=87),不能使用缩短类路径解决方法
C++ CreateProcess 无法从 Windows 7 上的套接字接收路径 (64)
用大量参数编译 GWT 代码——CreateProcess 的字符限制?