为什么Process.Start意外返回false

时间:2013-02-08 18:43:57

标签: c# .net windows service process

使用Process.Start来封装另一个可执行文件(不是文件类型)时,为什么它会返回false并且无法启动可执行文件而不是抛出异常?为了更清楚,文档提到如果启动流程资源,则返回为真;如果没有启动新的进程资源,则返回false(例如,如果重用现有进程)。"现有流程的所有解释都被重复使用"似乎是用于启动在处理它们的程序的现有实例中打开的文件(例如,启动在现有图像编辑器实例中打开的.jpg)。在此上下文中启动的可执行文件是内部编写的,不会阻止新实例执行。没有记录或应用程序甚至尝试启动的其他迹象。无法找到过程未开始的反馈。

值得注意的是,快速连续发布的可执行文件数量越多,问题就越可重现。生产环境中的相同代码似乎没有失败,但负载在许多机器上分布得更好。在测试环境中,100多个进程在一台机器上快速连续启动,而且最后7-10个进程是唯一未能启动的进程。控制进程能够检测启动时已经运行的进程,并且只启动那些当前未运行的进程。这看起来工作正常,当我们进行全新的启动时(所有100多个实例都被验证停止然后我们启动它们)7个左右无法启动但是我们可以重新启动控制进程和相同的可执行文件相同的设置成功运行。知道所有启动的进程具有不同的命令行参数的可执行文件可能很有用。控制进程是Windows服务,生成的可执行文件是命令行应用程序,不依赖于标准输入或输出流。

在解决此问题的过程中,为了安全起见,我确保启动外部应用程序的线程在单线程单元中运行,因为ShellExecuteEx可以依赖于此,但我相信框架现在可以解释这一点。我尝试在进程执行之间添加Thread.Sleep延迟,这似乎不会影响无法启动的应用程序数量(尝试从100ms到300ms的不同延迟,以及最近每个实例上升到1500ms左右后的延迟增加) )。

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);

1 个答案:

答案 0 :(得分:0)

我有点惊讶它没有抛出Win32Exception。尝试在Process.Start()失败后检索最后一个Win32错误。你这样做:

var errorCode = Marshal.GetLastWin32Error();

然后,假设您将收到Win32错误,请在此站点查找:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx