为什么批处理文件在从 Windows Forms 应用程序调用时不复制文件,但它在控制台应用程序中有效?

Why does the batch file not copy files when invoked from Windows Forms app but it works from Console app?

我有一个控制台应用程序和一个执行相同操作的 Winforms 应用程序。共同的功能在 class 中,被两者重复使用。

CopyRequiredFile,启动一个 windows 批处理文件,它使用 xcopy 将文件从网络文件夹复制到本地驱动器。但是,当从 Windows Forms 应用程序调用时,它不会复制文件

我是一名开发新手,正在尝试为 UI 自动化开发框架和一些内部工具。

为什么当我从控制台应用程序而不是 Windows 表单应用程序调用功能时复制文件有效?

我的控制台应用程序:

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.CreateRequiredDirectories(Progress);
            HelpersCopy.CopyRequiredFiles(Progress, true);
            HelpersCopy.StartHub(Progress);
            HelpersCopy.StartNode(Progress);

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

我的 Windows 表单应用程序: 只有与此问题相关的代码。

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

            txtOutput.Clear();
            HelpersCopy.CreateRequiredDirectories(progress);
            HelpersCopy.CopyRequiredFiles(progress, true);
            HelpersCopy.StartHub(progress);
            HelpersCopy.StartNode(progress);
        }

InvokeEx 是一种扩展方法,可在需要时调用操作。来自 Whosebug 的帮助!

很遗憾,我无法 post 图片,因为我没有所需的分数。因此,请在此处查看输出图像:https://www.flickr.com/photos/61600076@N05/sets/72157649781440604/

助手Class代码如果问题中不需要此代码,请告诉我。

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));
                process.BeginErrorReadLine();
                process.BeginOutputReadLine();
                process.WaitForExit();

                int ExitCode = process.ExitCode;

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

我的批处理文件

@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

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

您是否测试过将批处理文件放在 Windows Forms exe 可用的同一文件夹中? 您是否尝试过 运行 具有管理员权限的 windows 表单应用程序? 只是为了消除权限不足的可能性。

您是否还验证了执行代码的用户上下文以及文件夹是否具有用户上下文的权限?

winforms 应用程序中的问题(尽管在使用相同代码的控制台应用程序中从来没有任何问题)是由 xcopy 中的错误引起的,因为当您重定向其输出时,您也需要重定向其输入。因此,将此行添加到我的代码中的 ProcessInfo 对象,解决了这个问题。

RedirectStandardInput = true

有关此问题的更多信息: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ab3c0cc7-83c2-4a86-9188-40588b7d1a52/processstart-of-xcopy-only-works-under-the-debugger?forum=netfxbcl

希望这对某人有所帮助。