Click here to Skip to main content
11,705,212 members (47,678 online)
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 0:38am
Andy Lanng10.9K

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

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 550
1 OriginalGriff 244
2 ppolymorphe 126
3 CPallini 82
4 F-ES Sitecore 70
0 OriginalGriff 8,988
1 Sergey Alexandrovich Kryukov 8,272
2 CPallini 5,189
3 Maciej Los 4,726
4 Mika Wendelius 3,606


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