我有一个类处理 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());
}