Process.Start() of xcopy only works under the debugger?

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!



Answer this question

Process.Start() of xcopy only works under the debugger?

  • Praveen-Infokall

    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


  • dwphilippe

    are you using cmd.exe as your executable and '/c xcopy  [src] [optional dest]' as your arguments

  • Avi_zl

    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);
        }
       }
      }
     }
    }

     



  • crystalchunn

    As I recall, putting a "/" at the end of the destination path will force xcopy to treat it as a directory.


  • virtual machine

    Perhaps the directories are not right   And perhaps the error message is written to stderr

     


  • shrooman

    This is a quirk of xcopy.exe. If you redirect the output, you have to redirect the input as well.


  • Diego Vargas

    no I'm starting xcopy directly, no cmd shell involved.

    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 Smile) so I'm not too familiar with the system commands.

    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

  • tackett

    This was reminding me of other cases I've had in the past where something like "cmd /c COMMAND" would not run, but "cmd /c start /b COMMAND" or something like that would.

    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

  • Prakash Paghdal

    Try seting the working directory and checking the exit code. 



    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);
    }

     




  • Nickj_UK

    Thanks for the suggestions.  I'm still having the same problem.

    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!

  • andy72

    Thanks for looking into it, your class will work nicely.  Looks like if you run xcopy from a System.Process.Start("xcopy") [syntax may be slightly wrong but you get the idea] it'll work but then you can't redirect output and you get a window that pops up.  Oh well.  I feel like someone from M$ should look at this.  Thanks for the help!
  • zzzzzzzz

    ok, I think I fixed my issue... But in doing so, opened a whole new can of worms.

    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.


  • BN25

    thats the damndest thing. . . does the same thing here. the move comand works though.

    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   
    ---------------------------



  • Dead Man Inc

    This is an old thread...but I'm still using .NET 1.1 and just ran into this same problem, so I thought I'd see if anyone ever found out more about this apparent xcopy/.NET1.1 bug.

    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

  • Process.Start() of xcopy only works under the debugger?