C#启动FFmpeg进程时如何让工作目录/参数错误触发try/catch异常
问题根因
Process.Start() 仅在操作系统无法定位、拉起指定可执行文件(即你配置的ffmpeg.exe路径)时会立刻抛出原生异常。只要ffmpeg.exe可执行文件本身能被系统找到并启动,哪怕启动瞬间因非法参数、无效工作目录触发崩溃退出,Start() 方法都会正常执行返回,不会触发异常——这就是你现有try/catch逻辑只能捕获ffmpeg路径错误,抓不到工作目录、参数错误的核心原因。
另外你当前代码只重定向了标准输入流,没有重定向标准错误流,完全拿不到ffmpeg启动后输出的报错信息,自然没法判断启动是否真的成功。
修复步骤
1. 启动前增加手动参数校验
在调用进程启动逻辑前,先对关键配置做合法性校验,不符合要求直接抛出异常,即可被外层现有catch逻辑捕获:
- ffmpeg路径:必须非空,且对应文件真实存在
- 工作目录:如果配置了非空值,必须是真实存在的目录路径
- 启动参数:不能为纯空白字符串(可根据业务需要增加更细的参数规则校验)
2. 启动后捕获进程早期错误
对于前置校验无法覆盖的错误(如参数指向的文件不存在、ffmpeg不识别的参数格式等),需要重定向ffmpeg的标准错误流,检测进程启动后的短时间内是否异常退出,若退出则读取错误信息抛出异常。
修改后的完整代码
FFmpeg_Capture类的Start方法调整如下:
public void Start() { // 前置参数校验 if (string.IsNullOrWhiteSpace(outputDirectory)) throw new ArgumentNullException(nameof(outputDirectory), "ffmpeg.exe路径不能为空"); if (!File.Exists(outputDirectory)) throw new FileNotFoundException("指定的ffmpeg.exe路径不存在", outputDirectory); if (!string.IsNullOrWhiteSpace(workingDirectory) && !Directory.Exists(workingDirectory)) throw new DirectoryNotFoundException($"指定的工作目录不存在: {workingDirectory}"); if (string.IsNullOrWhiteSpace(arguments)) throw new ArgumentException("启动参数不能为空", nameof(arguments)); process = new Process(); process.StartInfo.FileName = outputDirectory; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; // 重定向标准错误流,读取ffmpeg报错 process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; process.EnableRaisingEvents = false; // 异步采集错误输出,避免缓冲区满导致进程卡死 string errorOutput = string.Empty; process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) errorOutput += e.Data + Environment.NewLine; }; process.Start(); // 启动错误流异步读取 process.BeginErrorReadLine(); // 等待最多500毫秒,检测进程是否因参数/配置错误早期退出 if (process.WaitForExit(500)) { process.Dispose(); throw new InvalidOperationException($"ffmpeg启动失败,错误信息: {errorOutput.Trim()}"); } errorMessage = false; startRecord = true; }
Form层的事件逻辑不需要大幅修改,现有catch块已经覆盖了异常捕获后的状态回滚、弹窗提示逻辑,Start()抛出的异常可以直接被现有逻辑捕获处理。
注:500毫秒的超时时间足够覆盖绝大多数参数错误、配置错误导致的ffmpeg即时退出场景,不会造成UI明显卡顿;正常启动的ffmpeg进程会在500毫秒超时后继续往下执行,不会被误判。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

