使用Process.Start时外壳另一个可执行文件(不是文件类型)为什么它会返回 false 并且无法启动可执行文件而不是抛出异常?更清楚地说,文档提到返回为“如果启动了流程资源,则返回 true;如果没有启动新的流程资源(例如,如果重用现有流程),则返回 false”。“重用现有进程”的所有解释似乎都是为了启动在处理它们的程序的现有实例中打开的文件(例如启动在现有图像编辑器实例中打开的 .jpg)。在这种情况下启动的可执行文件是内部编写的,不会阻止新实例的执行。不存在应用程序甚至尝试启动的日志记录或其他迹象。找不到关于为什么该过程没有开始的反馈。
值得注意的是,快速连续启动的可执行文件数量越多,该问题的重现性就越高。生产环境中的相同代码似乎没有失败,但负载在许多机器上分布得更好。在测试环境中,100 多个进程在单台机器上快速连续启动,并且几乎一致的是最后 7-10 个进程是唯一无法启动的进程。控制进程能够在启动时检测到已经运行的进程,并且只会启动那些当前未运行的进程。这似乎工作正常,当我们完全重新启动时(所有 100 多个实例都被验证已停止,然后我们启动它们)7 左右无法启动,但我们可以重新启动控制过程和相同的可执行文件相同的设置成功运行。知道所有启动的进程都是具有不同命令行参数的相同可执行文件可能很有用。控制进程是一个 Windows 服务,生成的可执行文件是命令行应用程序,不依赖于标准输入或输出流。
在解决此问题的过程中,为了安全起见,我已确保启动外部应用程序的线程在单线程单元中运行,因为 ShellExecuteEx 可以依赖于此,尽管我相信框架现在可以解决此问题。我尝试在进程执行之间添加 Thread.Sleep 延迟,这似乎不会影响未启动的应用程序的数量(尝试从 100 毫秒到 300 毫秒的不同延迟,最近每个实例达到 1500 毫秒左右后延迟增加)。
Windows 是否存在最大数量的子进程,或者当 Windows 尝试同时启动大量进程时可能会发生一些错误?对于执行失败的原因,我无法找到合理的答案。以下是启动可执行文件本身的位(一些内部内容已编辑,但所有框架代码都完好无损):
if (!Path.IsPathRooted(processPath))
{
processPath = Path.GetFullPath(Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
processPath));
}
ProcessStartInfo psi =
new ProcessStartInfo(processPath, args);
psi.UseShellExecute = true;
psi.CreateNoWindow = true;
Trace("Starting {0} {1}", processPath, args);
using (Process process = new Process())
{
process.StartInfo = psi;
bool success = process.Start();
if (!success)
{
// this is what doesn't make sense
}
}
Trace("Started {0} {1}", processPath, args);