|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Bug in .NET's Process model?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! 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! 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! > > 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! 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(); } } } -- Show quoteWilliam Stacey [MVP] "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! 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! Did you try the code?
-- Show quoteWilliam Stacey [MVP] "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! 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! It is difficult for us to keep guessing without seeing any code. Please
post the sample code that shows this problem. -- Show quoteWilliam Stacey [MVP] "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! 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); 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 -- Show quoteWilliam Stacey [MVP] "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); 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. |
|||||||||||||||||||||||