【问题标题】:Exe Process only works in VS2010 unit tests, not from MVC appExe 进程仅适用于 VS2010 单元测试,不适用于 MVC 应用程序
【发布时间】:2012-09-25 08:58:48
【问题描述】:

我有一个类来处理 exe 进程的执行,它是一个控制台应用程序(用 Fortran 编写!)。运行此程序时,用户必须先输入一个输入文件的名称(必须与 exe 存在于同一位置)和一个输出文件(尚不存在,但由 exe 生成。

在我对 Execute 方法的单元测试中(见下文),一切正常。输出文件正确生成。但是,当我从 MVC 应用程序中点击此方法时,exe 无法找到输入文件,即使它确实存在。我能想到的唯一解释是VS2010自动创建的“TestResults”文件夹在权限方面有所不同,或者单元测试过程有所不同。

    public void Execute(string inputFileName, string outputFileName, int timeoutMilliseconds)
    {
        if (outputFileName == null)
            throw new ArgumentNullException("outputFileName");
        else if (inputFileName == null)
            throw new ArgumentNullException("inputFileName");

        if (outputFileName == string.Empty)
            throw new ArgumentException("outputFileName must not be an empty string");
        else if (inputFileName == string.Empty)
            throw new ArgumentException("inputFileName must not be an empty string");

        if (!File.Exists(ConfigurationManager.AppSettings["dataPath"]  + inputFileName))
            throw new FileNotFoundException("File not found.", inputFileName);            

        Process p = new Process();
        p.StartInfo = GetProcessStartInfo();
        p.Start();

        string output = "";

        // Read up to line where program asks for input file name.
        while (output == "")            
            output = p.StandardOutput.ReadLine();            

        // Write the input file name.
        p.StandardInput.WriteLine(inputFileName);

        // Read up to line where program asks for output file name.
        output = "";
        while (output == "")            
            output = p.StandardOutput.ReadLine();            

        // Write the output file name.
        p.StandardInput.WriteLine(outputFileName);

        if(!p.WaitForExit(timeoutMilliseconds))
            throw new ApplicationException("The process timed out waiting for a response.");            
    }

    private ProcessStartInfo GetProcessStartInfo()
    {
        var startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardInput = true;
        startInfo.FileName = _exeFileLocation;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;            
        return startInfo;
    }

编辑:

我发现如果我尝试从 C 驱动器上的某个位置运行该进程,单元测试也会失败。在下面的代码中,如果我将“dataPath”设置为硬盘位置(例如“C:\DATALOCATION”),则进程失败,说它无法找到输入文件。但是,如果我将配置中的“dataPath”保留为空字符串,则单元测试会自动从 TestResults 文件夹的子目录运行该过程,并且一切正常!

    [TestMethod]
    public void ExeRunnerTest()
    {
        var studyData = // populate study data here
        var writer = new StudyDataFileWriter(studyData);

        // Write input
        string fileName = writer.WriteToFile();

        // Run 
        var exeRunner = new ExeRunner(ConfigurationManager.AppSettings["dataPath"] + "myProcess.exe");
        exeRunner.Execute(fileName, "outputFile", 10000);

        // Read output
        IStudyOutputFileReader reader = new StudyOutputFileReader(ConfigurationManager.AppSettings["dataPath"] + "outputFile");
        StudyOutput output = reader.Read();

        // Tests
        Assert.AreEqual(1, output.ConsumerSummary.ConsumerTypes.Count());
    }

【问题讨论】:

  • 我猜语言是C#,这就是我添加标签的原因。请始终在适用时添加适当的语言标签。它使对某些主题不感兴趣的人可以更轻松地过滤掉带有这些标签的问题。
  • .AppSettings["dataPath"] + "myProcess.exe" 正在将两根弦敲在一起。如果第一个字符串不以 \ 结尾,则它可能没有构建您想要的路径。考虑使用System.IO.Path.Combine()。它可能与工作目录有关,因此传递绝对文件名似乎是明智的。
  • Damien - 使用绝对路径使代码正常工作(无论出于何种原因),所以我很高兴。除非您想将其发布为答案,否则我无法将其标记为答案?

标签: c# asp.net-mvc visual-studio-2010 unit-testing process


【解决方案1】:

使用绝对路径使代码正常工作。工作目录一定有问题。

【讨论】:

    猜你喜欢
    • 2012-05-24
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    相关资源
    最近更新 更多