Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#
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 1:38am

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

  Print Answers RSS
0 OriginalGriff 5,170
1 DamithSL 4,357
2 Maciej Los 3,750
3 Kornfeld Eliyahu Peter 3,470
4 Sergey Alexandrovich Kryukov 2,851


Advertise | Privacy | Mobile
Web03 | 2.8.141216.1 | Last Updated 8 May 2013
Copyright © CodeProject, 1999-2014
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