I am trying to run a child process to xcopy files into another directory. xcopy is regular old Windows system xcopy. I am creating a new System.Diagnostics.Process, filling out some start info, then kicking it off with Process.Start(). When I run this code under the .NET debugger it works fine.
However, if I run my app outside the debugger, the xcopy child process fails to do anything. I've attached a debugger after I started my app outside the .NET IDE and although the child process appears to run, I get nothing from its stdout and the files I intend to xcopy are never copied. This child process (xcopy) does not hang... I do a Process.WaitForExit() after the Start() and the thread that kicks off the child process does not hang. Its almost as if the p.Start() call doesn't actually do anything. Any ideas
I'd post code but I don't have it here at the moment. The code is pretty much standard 'set start info and kick off child process' kinda stuff. Thanks!

Process.Start() of xcopy only works under the debugger?
Azam Abdul Rahim
xcopy returns 0 and nothing is sent to stdout or stderr when I run it outside the debugger. It returns 0 when run inside the debugger, along with the usual stdout and stderr messages one would expenct after an xcopy run.
The code I have creating the child process is a general method that starts other process. The method works just fine starting other processes throughout the execution of my app. I only see this issue with xcopy. I wonder if other system commands would behave similarly...
I've heard of Win32 apps calling a different CreateProcess() when run in the debugger, does the .NET framework do something like this Maybe the issue lies in what version of Process.Start() is actually called at runtime ( ). Thanks for the help!
GeoffW85
Adding the /I switch to xcopy fixes the issue. But...
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()
Both of these things should not have happened because xcopy was in the process of asking "is the destination a file or directory"... and was expecting input from the user.
dbw
ProcessStartInfo s = new ProcessStartInfo(ExecutablePath);
s.Arguments = args;
s.CreateNoWindow = true;
s.RedirectStandardOutput = true;
s.RedirectStandardError = true;
s.UseShellExecute = false;
s.WindowStyle = ProcessWindowStyle.Hidden;
s.WorkingDirectory = Path.GetDirectoryName(ExecutablePath);
using (Process p = Process.Start(s))
{
string standardOutput = p.StandardOutput.ReadToEnd();
string errorOutput = p.StandardError.ReadToEnd();
p.WaitForExit(30 * 1000);
int exitCode = p.ExitCode;
log.DebugFormat("ExitCode: {0}", exitCode);
log.DebugFormat("Standard Output: {0}", standardOutput);
log.DebugFormat("Standard Error Output: {0}", errorOutput);
}
DanKirkwoodJr
Haashole
I just hammered on this for a while, and I discovered a way of spawing xcopy with Process.Start() that works consistently. Will document below, in case this ever helps anyone else who is stung by this.
I should also point out a few details:
My symptoms are EXACTLY those reported by awm129 above. I'm on Windows Xp, and I have written a generic routine that calls Process.Start() using executable "cmd" and arguments "/c COMMAND" where I am passing in various things for COMMAND, including xcopy. Everything that I pass in except for xcopy works 100% of the time. I got xcopy to work, as I said, about 20% of the time.
These cases do not work for xcopy:
cmd /c xcopy ...
cmd /c start /b xcopy ...
cmd /c start /b cmd /c xcopy ...
cmd /c start /b /i cmd /c xcopy ...
cmd /c start /b /i xcopy ...
However, in same test case, I found that these next combinations, when passed
through Process.Start(), DO work 100% of the time for me:
cmd /c start /i xcopy ...
cmd /c start /i cmd /c xcopy ...
cmd /c start /i /min xcopy ...
I am going to try using the last one because it at least only opens the
annoying shell window on my toolbar, not on the desktop.
Go figure! This is a nasty and complex bug, and like I said, this is bringing back
memories of various other occasions where "chaining" various combinations of
cmd.exe / start / cmd.exe / start has seemed necessary to get a command to run.
I seem to recall that most of those cases involved batch files, and some of the time
the error mode was a shell or batch file that would never exit, even if you called
'exit'...
What I'll take away from this: Process.Start() and cmd.exe are BAD NEWS
when used together.
M. Bearden
henit
heres what I used:
ProcessStartInfo s = new ProcessStartInfo("cmd.exe");
s.Arguments = @"/c xcopy D:\foobar f:\foobar /e /y";
s.CreateNoWindow = true;
s.RedirectStandardOutput = true;
s.RedirectStandardError = true;
s.UseShellExecute = false;
s.WindowStyle = ProcessWindowStyle.Hidden;
int exitCode;
string standardOutput;
string errorOutput;
using (Process p = Process.Start(s))
{
standardOutput= p.StandardOutput.ReadToEnd();
errorOutput = p.StandardError.ReadToEnd();
p.WaitForExit(30*1000);
exitCode = p.ExitCode;
}
MessageBox.Show(this, string.Format("ExitCode: {0}\r"+
"Standard Output: \n\t{1}\r"+
"Standard Error Output:\n\t{2}\r",
exitCode,
standardOutput.Replace("\n","\n\t"),
errorOutput.Replace("\n","\n\t")));
}
in debug, results:
---------------------------
ExitCode: 0
Standard Output:
D:\foobar\foobar.txt
D:\foobar\foobas\foobas.txt
2 File(s) copied
Standard Error Output:
------------------------------------------------------
OK
---------------------------
in runtime:
ExitCode: 0
Standard Output:
Standard Error Output:
---------------------------
OK
---------------------------
JoeyNguyen
Asem Masri
you said Move works. Does Move 'move' whole directories That might be a good alternative. This is my first foray into the windows world (and after this silly bug maybe my last
I'm glad someone was able to duplicate the issue... at least I'm not crazy. My code is almost identical to what you have, thanks for posting what you wrote. Could this be some bug in .NET, or worse yet, Win32
DCMonkey
Crean
Xcopy is evil. It's a great command line utility, but calling it from programs is asking for trouble.
The URT has built in classes for handling all sorts of file operations.
The URT version of xcopy is this.
System.IO.File.Copy(source, destination);
You can't pass it things like *.*, so it's a little more work but wrapping in in a method and calling it in a loop isn't much trouble.
Source and destinations are strings. MSDN online has everything you need to know about the File and Directory class.
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemiofileclasstopic.asp
or Google "System.IO.File class" if you forget/lose the URL.
-Dustin Andrews
Phil Cowan
Seems to be a bug with .net as Executing CreateProcess on xcopy using win32 api works in both debug and runtime.
Move renames a foleder - doesn't work across volumes.
I didn't know xcopy was an exe - thought it was a shell command like dir and move therefore needing to be executed cia cmd.exe.
here's a class to copy System.IO.FileSystemInfo objects:
use it to copy directories and files (I guess its not necessary for Files as File already has a copy method.)
namespace FileSystemUtilities
{
public enum FileSystemItemType{ File , Folder }
public class FileSystemItem
{
System.IO.FileSystemInfo _obj;
public FileSystemItem(System.IO.FileSystemInfo obj)
{
_obj = obj;
}
public FileSystemItemType ItemType
{
get
{
return _obj is System.IO.FileInfo
FileSystemItemType.File :
FileSystemItemType.Folder;
}
}
public System.IO.FileSystemInfo Item
{
get
{
return this._obj;
}
}
public void Copy(string location)
{
if(!System.IO.Directory.Exists(location))
System.IO.Directory.CreateDirectory(location);
if (this.ItemType==FileSystemItemType.File)
{
if (System.IO.File.Exists(location + _obj.Name))
System.IO.File.Delete(location + _obj.Name);
System.IO.File.Copy( _obj.FullName, location + _obj.Name);
}
else
{
if (!System.IO.Directory.Exists(location + _obj.Name))
System.IO.Directory.CreateDirectory(location + _obj.Name);
System.IO.DirectoryInfo curr = _obj as System.IO.DirectoryInfo;
location+= _obj.Name + "\\";
foreach(System.IO.DirectoryInfo di in curr.GetDirectories())
{
FileSystemItem fi = new FileSystemItem(di);
fi.Copy(location);
}
foreach(System.IO.FileInfo fiCurr in curr.GetFiles())
{
FileSystemItem fi = new FileSystemItem(fiCurr);
fi.Copy(location);
}
}
}
}
}
Philip73
As I recall, putting a "/" at the end of the destination path will force xcopy to treat it as a directory.
Vince_Kennedy
User awm129 reported that adding a "/I" option made xcopy start working, even though "it should not have". I suspect that this was "randomness" instead. My own failure mode appears to be "random". I am calling xcopy from a .NET program and as I have run an identical test case over and over, it has worked about 20% of the time. There appears to be not pattern, except that it works two or three times in a row, then fails dozens of times in a row.
M. Bearden
Rynus_Rein
Perhaps the directories are not right And perhaps the error message is written to stderr