Why does not the batch file copy files when called from the Windows Forms application, but does it work from the Console application?


I have a Console app and a Winforms app that do the same. The common functionality is in a class being reused by both.

The CopyRequiredFile, starts a windows batch file which uses xcopy to copy files from a network folder to a local drive. But, when called from the Windows Forms app it doesn't copy the files.

I am a novice developer trying to develop framework and some internal tools for UI automation.

Why does it work to copy the files when I invoke the functionality from the Console application, but not from the Windows Forms Application?

My Console App:

public class Program
        private static readonly Action<string> OutputAction = s => Console.WriteLine(s);
        private static readonly IProgress<string> Progress = new Progress<string>(OutputAction);

        public static void Main(string[] args)
            HelpersCopy.CopyRequiredFiles(Progress, true);

            Console.WriteLine("Press any key to continue...");

My Windows Forms app: Only code that is relevant to this question.

private void button1_Click(object sender, EventArgs e)
            Action<string> outputAction = s => txtOutput.InvokeEx(t => t.Text += s + Environment.NewLine);
            IProgress<string> progress = new Progress<string>(outputAction);

            HelpersCopy.CopyRequiredFiles(progress, true);

InvokeEx is an extension method to invoke the action if required. Help from stackoverflow!

Unfortunately, I cannot post images because I don't have the required points. So, please see the output images here: https://www.flickr.com/photos/[email protected]/sets/72157649781440604/

Helpers Class Code Please let me know if this code is not required in the question.

public class HelpersCopy
        public static void CopyRequiredFiles(IProgress<string> progress, bool hideWindow = false)
            progress.Report(string.Format("Copying latest version of executables...{0}", Environment.NewLine));
            var currentDirectory = Directory.GetCurrentDirectory();
            ExecuteCommand(String.Format(@"{0}\Copy latest Selenium files.bat", currentDirectory), progress, hideWindow: hideWindow);
            progress.Report(string.Format("\r\nLatest version of executables copied successfully{0}", Environment.NewLine));

        private static void ExecuteCommand(string fileName, IProgress<string> progress, string command = null, bool hideWindow = true)
            if (hideWindow)
                var processInfo = new ProcessStartInfo(fileName, command)

                    CreateNoWindow = true,
                    UseShellExecute = false,
                    // *** Redirect the output ***
                    RedirectStandardError = true,
                    RedirectStandardOutput = true

                var process = new Process { StartInfo = processInfo, EnableRaisingEvents = true };
                process.ErrorDataReceived += (sender, args) => progress.Report(args.Data);
                process.OutputDataReceived += (sender, args) => progress.Report(args.Data);
                var started = process.Start();
                progress.Report(string.Format("process started: {0}", started));
                progress.Report(string.Format("process id: {0}", process.Id));
                progress.Report(string.Format("process start info: {0} {1}", process.StartInfo.FileName, process.StartInfo.UserName));

                int ExitCode = process.ExitCode;

                progress.Report(string.Format("ExitCode: {0}{1}", ExitCode, Environment.NewLine));
                var process = Process.Start(fileName, command);
                if (process.HasExited)
                    throw new Exception(string.Format("Process exited. Exit code: {0}", process.ExitCode));

My batch file

@echo off

echo Deleting existing mappings...

net use z: /delete /yes

echo Mapping network drives...

net use z: \\company-filestore\Selenium /user:company-filestore\Automation Selen1um

cd "Hub and Node Executables"

echo Copying latest Selenium jars...
xcopy "z:\Hub and Node Executables" "C:\Selenium\" /R /Y /S /Z
echo Finished copying latest Selenium jars...

echo All done

The issue in winforms app (although, there was never any issue in console app using the same code) was being caused by a bug in xcopy in that when you redirect its output you need to redirect its input as well. So, adding this line to the ProcessInfo object in my code, fixed the issue.

RedirectStandardInput = true

More information on the issue is here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ab3c0cc7-83c2-4a86-9188-40588b7d1a52/processstart-of-xcopy-only-works-under-the-debugger?forum=netfxbcl

Hope this helps someone.