3

While using Process.Start to shell another executable (not a file type) why would it return false and fail to start the executable rather than throwing an exception? To be more clear, the documentation mentions the return to be "true if a process resource is started; false if no new process resource is started (for example, if an existing process is reused)." All explanations of "an existing process is reused" appear to be for launching files that open in an existing instance of the program that handles them (like starting a .jpg that opens in an existing image editor instance). The executable launched in this context is authored in-house and does nothing to prevent new instances from executing. No logging or other signs that the application even attempted to start are present. Feedback for why the process was not started is nowhere to be found.

It is worth noting that the issue becomes more reproducible the higher the number of executables launched in rapid succession. The same code in production environments does not appear to be failing, but the load is distributed better across many machines. In the test environment 100+ processes are started in rapid succession on a single machine and pretty consistently the last 7-10 are the only ones that fail to launch. The control process is able to detect the processes already running when it starts and will only start those not currently running. This appears to be working correctly, and when we do a full fresh start (all 100+ instances are verified to be stopped and then we start them) 7 or so fail to start but then we can restart the control process and the same executables with the same settings run successfully. It may be useful to know that all processes started are of the same executable with different command line arguments. The control process is a Windows Service, the spawned executables are command line applications with no dependency on the standard input or output streams.

In the process of troubleshooting this issue, to be safe, I have ensured the thread starting the external applications is running in a single-threaded apartment because ShellExecuteEx can depend on this, though I believe the framework now accounts for this. I have tried adding Thread.Sleep delays between process executions which do not appear to effect the quantity of applications that do not start (with varying delays attempted from 100ms to 300ms, and most recently an increasing delay after each instance going up to 1500ms or so).

Is there perhaps a maximum number of child processes imposed by windows, or perhaps some bug that happens when windows is trying to launch tons of processes at the same time? I have not been able to find a reasonable answer to why the execution fails. Here are the bits that launch the executable itself (some internals redacted, but all framework code intact):

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

1 に答える 1

0

Win32Exception がスローされなかったことに少し驚いています。Process.Start() が失敗した後、最後の Win32 エラーを取得してみてください。あなたはそれを行います:

var errorCode = Marshal.GetLastWin32Error();

次に、Win32 エラーが発生すると仮定して、次のサイトを参照してください。

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

于 2015-07-30T21:47:15.943 に答える