Home All Groups Group Topic Archive Search About

Bug in .NET's Process model?

Author
12 Oct 2005 5:12 PM
awm129
This may not be the correct place for this, but I think it is something an
MVP should take a look at.  Check out this thread over on the developer
forums:
http://forums.microsoft.com/msdn/ShowPost.aspx?postid=103823&isthread=true&authhash=72016b4564ad0e50618e5f8d207363d1167743bd&ticks=632641892841980170

I apologize if posting a link to another thread is bad practice, if so, tell
me.  Thanks!

Author
13 Oct 2005 2:04 AM
Lau Lei Cheong
I guess this could be a particular problem of xcopy that it doesn't work
well with pipeline. See the following link for someone experienced the same
problem for VB6:
http://www.flexbeta.net/forums/lofiversion/index.php/t3090.html

Show quote
"awm129" <awm***@discussions.microsoft.com> ¼¶¼g©ó¶l¥ó·s»D:B92A259C-847B-4BA9-AE50-0CA21BC0B***@microsoft.com...
> This may not be the correct place for this, but I think it is something an
> MVP should take a look at.  Check out this thread over on the developer
> forums:
>
> http://forums.microsoft.com/msdn/ShowPost.aspx?postid=103823&isthread=true&authhash=72016b4564ad0e50618e5f8d207363d1167743bd&ticks=632641892841980170
>
> I apologize if posting a link to another thread is bad practice, if so,
> tell
> me.  Thanks!
Author
13 Oct 2005 2:26 AM
Lau Lei Cheong
I've not performed any testing, but MSDN suggested that you should perform
read from outputs before WaitForExit(), but that is for another problem...
see if it helps...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdiagnosticsprocessstartinfoclassredirectstandardoutputtopic.asp

Show quote
"Lau Lei Cheong" <leu***@yehoo.com.hk> ¼¶¼g©ó¶l¥ó·s»D:%23$8LEl5zFHA.3***@TK2MSFTNGP10.phx.gbl...
>I guess this could be a particular problem of xcopy that it doesn't work
>well with pipeline. See the following link for someone experienced the same
>problem for VB6:
> http://www.flexbeta.net/forums/lofiversion/index.php/t3090.html
>
> "awm129" <awm***@discussions.microsoft.com> ¼¶¼g©ó¶l¥ó·s»D:B92A259C-847B-4BA9-AE50-0CA21BC0B***@microsoft.com...
>> This may not be the correct place for this, but I think it is something
>> an
>> MVP should take a look at.  Check out this thread over on the developer
>> forums:
>>
>> http://forums.microsoft.com/msdn/ShowPost.aspx?postid=103823&isthread=true&authhash=72016b4564ad0e50618e5f8d207363d1167743bd&ticks=632641892841980170
>>
>> I apologize if posting a link to another thread is bad practice, if so,
>> tell
>> me.  Thanks!
>
>
Author
13 Oct 2005 2:38 AM
Lau Lei Cheong
Having some Googling shows the following article:
http://support.microsoft.com/?id=133302

This suggest that a well number of "good old applications" will also have
the same behaviour, but wait - this should have been fixed at VC++ 4.0...

Show quote
"awm129" <awm***@discussions.microsoft.com> ¼¶¼g©ó¶l¥ó·s»D:B92A259C-847B-4BA9-AE50-0CA21BC0B***@microsoft.com...
> This may not be the correct place for this, but I think it is something an
> MVP should take a look at.  Check out this thread over on the developer
> forums:
>
> http://forums.microsoft.com/msdn/ShowPost.aspx?postid=103823&isthread=true&authhash=72016b4564ad0e50618e5f8d207363d1167743bd&ticks=632641892841980170
>
> I apologize if posting a link to another thread is bad practice, if so,
> tell
> me.  Thanks!
Author
13 Oct 2005 6:07 AM
William Stacey [MVP]
This works fine in debug or release mode.  I suspect your issue is Xcopy is
posting a message asking if target is a Dir name or a file - as it does if
target dir does not exist:
"C:\>xcopy dir1 dir5 /e/y
Does dir3 specify a file name
or directory name on the target
(F = file, D = directory)?"

So you never see any stdOut and process seems to hang, but is actually
waiting on input from you.  As your blocking on stdOut, you never get the
point of waiting for process to exit.  So your stuck.  You need to read std
out and std err in seperate threads and start those before you block waiting
for exit.  Then you capture the error.  Here is example.  Could use some
more work, but shows the msg xcopy gives you asking if dir5 is a directory:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace XcopyTest
{
    class Program
    {
        static void Main(string[] args)
        {
            ProcessStartInfo s = new ProcessStartInfo("cmd.exe");
            s.Arguments = @"/c xcopy c:\dir1 c:\dir5 /e /y";
            s.CreateNoWindow = true;
            s.RedirectStandardOutput = true;
            s.RedirectStandardError = true;
            s.UseShellExecute = false;
            s.WindowStyle = ProcessWindowStyle.Hidden;
            int exitCode;

            Process p = new Process();
            p.StartInfo = s;
            p.Start();

            StringBuilder sbErr = new StringBuilder();
            Thread errThread = new Thread(delegate()
            {
                string line = null;
                try
                {
                    while ( (line = p.StandardError.ReadLine()) != null )
                    {
                        sbErr.AppendLine(line);
                    }
                }
                catch ( Exception ex )
                {
                    Console.WriteLine("******** " + ex.Message);
                }
            });
            errThread.Start();

            StringBuilder sbOut = new StringBuilder();
            Thread stdThread = new Thread(delegate()
            {
                string line = null;
                try
                {
                    while ( (line = p.StandardOutput.ReadLine()) != null )
                    {
                        sbOut.AppendLine(line);
                    }
                }
                catch ( Exception ex )
                {
                    Console.WriteLine("******** " + ex.Message);
                }
            });
            stdThread.Start();

            if ( !p.WaitForExit(5 * 1000) )
            {
                p.Kill();
                stdThread.Interrupt();
                errThread.Interrupt();
            }
            stdThread.Join();
            errThread.Join();
            exitCode = p.ExitCode;
            p.Close();

            Console.WriteLine("ExitCode:" + exitCode);
            Console.WriteLine("Std out:"+ sbOut.ToString());
            Console.WriteLine("Std Err:"+ sbErr.ToString());
            Console.ReadLine();
        }
    }
}

--
William Stacey [MVP]

Show quote
"awm129" <awm***@discussions.microsoft.com> wrote in message
news:B92A259C-847B-4BA9-AE50-0CA21BC0B7E2@microsoft.com...
> This may not be the correct place for this, but I think it is something an
> MVP should take a look at.  Check out this thread over on the developer
> forums:
>
> http://forums.microsoft.com/msdn/ShowPost.aspx?postid=103823&isthread=true&authhash=72016b4564ad0e50618e5f8d207363d1167743bd&ticks=632641892841980170
>
> I apologize if posting a link to another thread is bad practice, if so,
> tell
> me.  Thanks!
Author
13 Oct 2005 1:07 PM
awm129
I had thought that was the issue as well, but the behavior I'm seeing is a
valid return code and no stdout, not a hung process (I'm using the /I swith
to avoid the dir issue, I'm also starting xcopy directly, not as an argument
to cmd).  The process DOES return with a 0 exit code, it just hasn't copied
files or spit anything out to stdout or stderr.  Also, that doesn't explain
why it works when run inside .NETs debugger yet fails when it is run by
windows outside of the IDE.  Attaching the debugger after the process has
already been started outside of the IDE also shows that the process does not
hang.  Thanks for the suggestions!
Author
13 Oct 2005 1:50 PM
William Stacey [MVP]
Did you try the code?

--
William Stacey [MVP]

Show quote
"awm129" <awm***@discussions.microsoft.com> wrote in message
news:26A76AFD-CD35-4369-84E7-28B6309484B0@microsoft.com...
>I had thought that was the issue as well, but the behavior I'm seeing is a
> valid return code and no stdout, not a hung process (I'm using the /I
> swith
> to avoid the dir issue, I'm also starting xcopy directly, not as an
> argument
> to cmd).  The process DOES return with a 0 exit code, it just hasn't
> copied
> files or spit anything out to stdout or stderr.  Also, that doesn't
> explain
> why it works when run inside .NETs debugger yet fails when it is run by
> windows outside of the IDE.  Attaching the debugger after the process has
> already been started outside of the IDE also shows that the process does
> not
> hang.  Thanks for the suggestions!
Author
13 Oct 2005 1:35 PM
awm129
OK, turns out I wasn't using the /I switch.  Adding this switch seems to fix
the immediate problem, yet raises even more questions. 

1)  Why did this work when run in the context of the .NET IDE debugger
without the /I switch?
2)  Why did the debugger, when attached to this process running outside of
the IDE, step past the p.WaitForExit()?

Thanks!
Author
13 Oct 2005 1:48 PM
William Stacey [MVP]
It is difficult for us to keep guessing without seeing any code.  Please
post the sample code that shows this problem.

--
William Stacey [MVP]

Show quote
"awm129" <awm***@discussions.microsoft.com> wrote in message
news:8FF6BB23-BB55-4835-83A8-17DF24143E1D@microsoft.com...
> OK, turns out I wasn't using the /I switch.  Adding this switch seems to
> fix
> the immediate problem, yet raises even more questions.
>
> 1)  Why did this work when run in the context of the .NET IDE debugger
> without the /I switch?
> 2)  Why did the debugger, when attached to this process running outside of
> the IDE, step past the p.WaitForExit()?
>
> Thanks!
Author
13 Oct 2005 2:10 PM
awm129
Yeah, i shoulda put this up to begin with, but I have to manually type it in
so I was tryng to avoid it...


/*************************************************

System.String output = "";

System.Diagnostics.Process p = new System.Diagnostics.Process();
//searches PATH for the executable
p.StartInfo.Filename = "xcopy.exe";
p.Arguments = "C:\\dir1 C:\\dir2 /E /Y /V /I";
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();

//read stdout and stderr before waiting for exit
output += p.StandardOutput.ReadToEnd();
output += p.StandardError.ReadToEnd();

p.WaitForExit();

long l = p.ExitCode;
System.Diagnostics.Debug.WriteLine("returned: " + l.ToString() + " :: " +
output);
Author
13 Oct 2005 9:58 PM
William Stacey [MVP]
Debug.WriteLine does not output anything in Release mode - only in debug
mode.  So the below code works in debug and release:
            System.String output = "";

            System.Diagnostics.Process p = new System.Diagnostics.Process();
            //searches PATH for the executable
            p.StartInfo.FileName = "xcopy.exe";
            p.StartInfo.Arguments = "C:\\dir1 C:\\dir5 /E /Y /V /I";
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.Start();

            //read stdout and stderr before waiting for exit
            output += p.StandardOutput.ReadToEnd();
            output += p.StandardError.ReadToEnd();

            p.WaitForExit();

            long l = p.ExitCode;
            Console.WriteLine("returned: " + l.ToString() + " :: " +
output);
            Console.WriteLine("Done.");
            Console.ReadLine();

Couple other points.
1)  For console programs, I turn off the redirect to Quick Console to help
me avoid some of these issues.
2) If this is a general method, I would read both std out and std err in
seperate threads so you don't block forever if you have some program waiting
for input for some unknown reason.
HTH
--
William Stacey [MVP]

Show quote
"awm129" <awm***@discussions.microsoft.com> wrote in message
news:C374CD22-FEAC-41A3-BB94-BC54375B26FC@microsoft.com...
> Yeah, i shoulda put this up to begin with, but I have to manually type it
> in
> so I was tryng to avoid it...
>
>
> /*************************************************
>
> System.String output = "";
>
> System.Diagnostics.Process p = new System.Diagnostics.Process();
> //searches PATH for the executable
> p.StartInfo.Filename = "xcopy.exe";
> p.Arguments = "C:\\dir1 C:\\dir2 /E /Y /V /I";
> p.StartInfo.RedirectStandardError = true;
> p.StartInfo.RedirectStandardOutput = true;
> p.StartInfo.UseShellExecute = false;
> p.StartInfo.CreateNoWindow = true;
> p.Start();
>
> //read stdout and stderr before waiting for exit
> output += p.StandardOutput.ReadToEnd();
> output += p.StandardError.ReadToEnd();
>
> p.WaitForExit();
>
> long l = p.ExitCode;
> System.Diagnostics.Debug.WriteLine("returned: " + l.ToString() + " :: " +
> output);
Author
20 Oct 2005 8:38 PM
awm129
this is a general method.  After looking into it more, I get

"The path is not of a legal form"

from either stdout or stderr.... I don't think the xcopy binary even
contans that string.  But xcopy seems to work fine if I just use
System.Diagnostics.Process.Strat("xcopy", args);  Again, I only get this
strange behavior when I run the app outside the debugger.

AddThis Social Bookmark Button