简体   繁体   中英

Getting an error when attempting to execute multiple commands

The project makes many different calls to the command line for a variety of purposes. To make this easier, I wrote a method that simply requires a person to enter the command in as a parameter :

public string AsyncCommandCall(string sCommand, List<string> lOutput, int timeout)
{
    if (!sCommand.ToLower().Substring(0, 5).Contains("/k"))
        sCommand = "/k " + sCommand;
    using(Process process = new Process())
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.FileName = "cmd.exe";

        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardError = true;
        startInfo.UseShellExecute = false;
        startInfo.Arguments = sCommand;
        startInfo.CreateNoWindow = true;

        process.StartInfo = startInfo;

        List<string> output = new List<string>();
        List<string> error = new List<string>();
        using(AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
        using(AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
        {
            process.OutputDataReceived += (sender, e) =>
            {
                if (e.Data == null)
                {
                    outputWaitHandle.Set();
                }
                else
                {
                    if(!String.IsNullOrEmpty(e.Data))
                        output.Add(e.Data);
                }
            };
            process.ErrorDataReceived += (sender, e) =>
            {
                if(e.Data == null)
                {
                    errorWaitHandle.Set();
                }
                else
                {
                    output.Add(e.Data);
                }
            };

            process.Start();

            process.BeginErrorReadLine();
            process.BeginOutputReadLine();

            if(process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout))
            {
                m_sCmdOutput.Clear();
                m_sCmdError.Clear();
                m_sCmdOutput.AddRange(output);
                m_sCmdError.AddRange(error);
                if(lOutput != null)
                {
                    lOutput.AddRange(output);
                }
                return AggregateList(output);
            }
            else
            {
                process.Close();

                //a time out doens't necessarily mean that stuff didn't happen, it's likely that it didn't process.

                if(error.Count > 0)
                {
                    m_sCmdError.Clear();
                    m_sCmdError.AddRange(error);
                }
                Debug("Thread time out for " + sCommand);
                if (output.Count > 0)
                {
                    m_sCmdOutput.Clear();
                    m_sCmdOutput.AddRange(output);
                    if (lOutput != null)
                    {
                        lOutput.AddRange(output);
                    }
                    return (AggregateList(output));
                }
                else
                {
                    Debug("Returning null");
                    return null;
                }
            }
        }
    }

}

The reason I am calling it asynchronously is that some of the commands I'm calling aren't guaranteed to work, so this ideally would allow me to try again if it times out.

When running my program, I noticed that one command, "time /t" would always timeout. To investigate, I tried running the code independently in the main loop of my program, and surprisingly it ran.

I became curious why this exact same command executed in once place while failing to run in another place. I ran another test where I placed the command call into a while loop, and soon found that the command calls stopped working as expected after exactly 4 AsyncCommandCall method calls. Looking back through my code, there were exactly 4 command calls before I called "time /t". I'm wondering if this is a bug in the api or if I'm doing something else wrong

Before anyone suggests it, I should also note that I did write a synchronous command call method that does not contain a "using" statement, but running it causes a hang on "process.WaitForExit()". Any help would be greatly appreciated.

EDIT

I noticed during my testing that if I increase the timeout that I pass as a parameter, more iterations are successfully called. Is there some kind of buffer that can be cleared so that the process time doesn't increase with each call?

As it turns out, this problem was dependent on the /k parameter that the method added to each command call. The /k flag tells the console to keep the output open, causing things like consistent timeouts using this asynchronous method, clogging system memory, and preventing process.WaitForExit() from returning. Instead, I am now using the /c flag before each command call and am successfully reading the output from each command. In calling AsyncCommandCall(command, null, 100) 1000 times in a row looping through three commands (An echo , a dir , and a psexec ), there were 0 timeouts and 0 failed reads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM