Click here to Skip to main content
12,076,206 members (48,787 online)
Rate this:
 
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
Andy Lanng16.1K

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.160208.1 | Last Updated 8 May 2013
Copyright © CodeProject, 1999-2016
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