如何将带管道的CMD命令转换为System.Diagnostics.ProcessStartInfo参数
问题分析
问题出在CMD命令参数的转义处理上。当通过Process调用cmd.exe并传递带管道(|)和引号的命令时,C#字符串中的引号未被正确转义,导致cmd.exe无法识别管道操作——它会把| find "pdf:Keywords"当作type命令的参数,而非独立的后续命令。
解决方案
1. 正确转义命令参数
修改Arguments赋值,将整个CMD命令用双引号包裹,同时把命令内部的双引号转义为两个双引号(C#字符串中表示双引号的标准方式):
startInfo.Arguments = $"/c \"type \"\"{fileInfo.FullName}\"\" | find \"\"pdf:Keywords\"\"\"";
或者使用逐字字符串(@前缀)提升可读性:
startInfo.Arguments = $@"/c ""type """"{fileInfo.FullName}"""" | find """"pdf:Keywords""""";
这样cmd.exe会正确解析管道符号,将type的输出传递给find命令。
2. 优化输出读取逻辑
原代码中的while(!process.HasExited)循环是多余的,ReadToEnd()会阻塞直到进程结束并读取所有输出。简化后的读取逻辑如下:
process.Start(); string output = process.StandardOutput.ReadToEnd(); process.WaitForExit();
添加WaitForExit()确保进程完全退出后再处理输出,避免未完成读取的情况。
完整修正代码
Process process = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo(); process.StartInfo = startInfo; startInfo.WorkingDirectory = importFileDirectoryInfo.FullName; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.FileName = "cmd.exe"; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; // 转义后的命令参数 startInfo.Arguments = $@"/c ""type """"{fileInfo.FullName}"""" | find """"pdf:Keywords"""""; process.Start(); // 读取输出并等待进程结束 string output = process.StandardOutput.ReadToEnd(); process.WaitForExit();
替代方案(可选)
如果不想依赖cmd.exe的管道解析,可以分开执行两个进程,手动传递输出:先执行type命令读取文件内容,再将输出传递给find.exe。不过这种方式需要额外处理流传递,不如直接修正cmd参数简便。
内容的提问来源于stack exchange,提问作者user3121062
相关产品推荐
相关产品推荐

