Click here to Skip to main content
13,042,819 members (76,219 online)
Rate this:
 
Please Sign up or sign in to vote.
See more:
Hi,

The original problem:
I am trying to prove an issue with paused processes. I am 99.9% sure that my application (that I inherited) is only reading from the stdout but has redirected both stdout and stderr. I think that the stderr has filled the output buffer (about 1k?) and so the process cannot output the remaining stdout.

My fix:
I have changed the code to use the events, as it should have done. I have created a test case to runs the old code over a simple batch file that outputs to the stdout and stderr and sure enough, it pauses.

What I have to do now (>_<):
What I have been asked to do is show the powers that be a more direct proof that I have solved the issue at hand. The only way I can see that I can do this without actually changing the live code, is to read from one of the paused processes that pop up on the live system.

Q:
1 - is this possible?
2 - how?

Thanks ^_^


Old code that's in the live system (it is pretty old)
    public class OldCommand
    {
        protected string _executableName;    // eg: rsh.exe
        private string _workingDirectory;  // where the command will run
        private string _stdoutOutput = "";
        private string _stderrOutput = "";
        protected Boolean _log_output = true;
        public Boolean LogToFile;
        private String _logfileName = "";
        private int _timeout;
 
        public String LogFilename
        {
            get { return _logfileName; }
        }
 
        /// <summary>
        /// In milliseconds
        /// </summary>
        public int Timeout
        {
            get { return _timeout; }
            set { _timeout = value; }
        }
 
        public OldCommand(string executableName)
        {
            _executableName = executableName;
        }
 
        public string ExecutableName
        {
            get { return _executableName; }
            set { _executableName = value; }
        }
 
        //protected virtual string options
        //{
        //    get { return ""; }
        //}
 
        public string WorkingDirectory
        {
            set { _workingDirectory = value; }
            get { return _workingDirectory; }
        }
 
        public string Output
        {
            get
            {
                return _stdoutOutput + _stderrOutput;
            }
        }
        public string StdoutOutput
        {
            get
            {
                return _stdoutOutput;
            }
        }
        public string StderrOutput
        {
            get
            {
                return _stderrOutput;
            }
        }
 
        public Boolean LogOutput
        {
            get { return _log_output; }
            set { _log_output = value; }
        }
 

        private int _pid = 0;
        public int Kill()
        {
            if(_pid>0)
            {
                try
                {
                    Process p = Process.GetProcessById(_pid);
                    p.Kill();
                    return _pid;
                }catch(ArgumentException)
                {
                    return 0;
                }
            }
            return _pid;
        }
 
        public virtual int Execute(string options)
        {
            // execute the process
            ProcessStartInfo processInfo = new ProcessStartInfo(_executableName, options);
            Log.WriteLineTrack("Command.Execute: " + _executableName + " " + options);
 
            // Notes:
            // 1. I think CreateNoWindow has to be true to prevent the launched cmd file truing to access a desktop (and failing)
            // 2. the credentials must have access to all drives required to fulfill the supplied command line
 
            processInfo.RedirectStandardOutput = true;
            processInfo.RedirectStandardError = true;
            processInfo.CreateNoWindow = true;
            processInfo.UseShellExecute = false;
            processInfo.WorkingDirectory = WorkingDirectory;
 
            Process rcpProcess = Process.Start(processInfo);
 
            _pid = rcpProcess.Id;
 
            // capture stdout
            String line = null;
            StringBuilder strbStdout = new StringBuilder();
            StreamReader outputStream = rcpProcess.StandardOutput;
            StreamWriter logSw = null;
 
            if (LogToFile)
            {
                _logfileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                logSw = new StreamWriter(_logfileName);
            }
            while ((line = outputStream.ReadLine()) != null)
            {
                if (LogToFile)
                {
                    logSw.WriteLine(line);
                }
                else
                    strbStdout.AppendLine(line);
            }
            outputStream.Close();
            outputStream.Dispose();
            // ...and stderr
 

            StringBuilder strbStderr = new StringBuilder();
            outputStream = rcpProcess.StandardError;
            while ((line = outputStream.ReadLine()) != null)
            {
                if (LogToFile)
                {
                    logSw.WriteLine(line);
                }
                else
                    strbStderr.AppendLine(line);
            }
            outputStream.Close();
            outputStream.Dispose();
 
            //_commandOutput = strbStdout.ToString() + strbStderr.ToString();
            _stdoutOutput = strbStdout.ToString();
            _stderrOutput = strbStderr.ToString();
 
            if (_log_output)
            {
                // write to log file with delimeters between out and err
                StringBuilder strbOutput = new StringBuilder();
                strbOutput.Append("<stdout>");
                strbOutput.Append(strbStdout.ToString());
                strbOutput.Append("</stdout>\n<stderr>");
                strbOutput.Append(strbStderr.ToString());
                strbOutput.Append("</stderr>");
                Log.WriteLineDebug(strbOutput.ToString());
            }
 
            if (LogToFile && logSw != null)
            {
                logSw.Close();
                logSw.Dispose();
            }
            // continue only when completed
            if (_timeout != 0)
            {
                rcpProcess.WaitForExit(_timeout);
            }
            else
            {
                rcpProcess.WaitForExit(); //can take a millisecs tiumeout arg
            }
            int rc = rcpProcess.ExitCode;
            rcpProcess.Dispose();
            // return: 0 = OK, other = error
            return rc;
        }
 
    }

my test case batch
@echo off
 
SETLOCAL 
set iterations=0;
echo %iterations%
 
:start
echo "out"
echo "error" >&2
set /a iterations=%iterations%+1
echo %iterations%
if %iterations% lss 1000 GOTO :start

The old_command in use
OldCommand oCmd = new OldCommand(@"cmd.exe");
    bool oldthreadfailed = false;
    Thread thread =
        new Thread(() =>
            oCmd.Execute(
                @"/c C:\Tests\RshTest.bat"));
    thread.Start();
    bool completed = thread.Join(new TimeSpan(0, 1, 0));
    if(!completed)
    {
        oCmd.Kill();
        thread.Join(new TimeSpan(0, 0, 5));
        thread.Abort();
        oldthreadfailed = true;
    }
Posted 8-May-13 0:38am
Andy Lanng21.4K

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web02 | 2.8.170713.1 | Last Updated 8 May 2013
Copyright © CodeProject, 1999-2017
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100