C#:调用 php 脚本并能够停止它

C#: Calling a php script and beeing able to stop it

我目前正在开发一个 C# 程序,它需要调用本地 PHP 脚本并将其输出写入文件。问题是,我需要能够停止脚本的执行。

首先,我尝试调用 cmd.exe 并让 cmd 将输出写入工作正常的文件。但我发现,终止 cmd 进程并不会停止 php cli。

所以我尝试直接调用 php,重定向其输出并将其从 C# 代码写入文件。但是这里的问题似乎是,php cli 在脚本完成后不会终止process.WaitForExit() 不会 return,即使我确定脚本已完全执行。

我无法为 WaitForExit() 设置超时,因为根据参数,脚本可能需要 3 分钟或例如。 10 小时。

我不想杀死一个随机的 php cli,目前可能还有其他 运行。

从 C# 调用本地 php 脚本、将其输出写入文件并能够停止执行的最佳方法是什么?

这是我当前的代码:

// Create the process
var process = new System.Diagnostics.Process();
process.EnableRaisingEvents = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "php.exe";
// CreateExportScriptArgument returns something like "file.php arg1 arg2 ..."
process.StartInfo.Arguments = CreateExportScriptArgument(code, this.content, this.options);
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.RedirectStandardOutput = true;

// Start the process or cancel, if the process should not run
if (!this.isRunning) { return; }
this.currentProcess = process;
process.Start();

// Get the output
var output = process.StandardOutput;

// Wait for the process to finish
process.WaitForExit();
this.currentProcess = null;

要终止我正在使用的进程:

// Mark as not running to prevent starting new
this.isRunning = false;

// Kill the process
if (this.currentProcess != null)
{
  this.currentProcess.Kill();
}

感谢阅读!

编辑

cli 没有 return 似乎不可重现。当我测试一个不同的脚本(没有参数)时它可以工作,可能是脚本或参数的传递。

运行 我的 cmd 脚本工作正常,所以脚本应该不是问题

编辑 2

禁用 RedirectStandardOutput 时,cli 退出。可能是我需要在过程完成之前读取输出吗?或者当某种缓冲区已满时,进程是否等待?

编辑 3:问题已解决

感谢 VolkerK,我/我们找到了解决方案。问题是,当未读取输出时,WaitForExit() 没有被调用(可能是由于标准输出中的缓冲区已满)。我的脚本写了很多输出。

对我有用的:

process.Start();

// Get the output
var output = process.StandardOutput;

// Read the input and write to file, live to avoid reading / writing to much at once
using (var file = new StreamWriter("path\file", false, new UTF8Encoding()))
{
    // Read each line
    while (!process.HasExited)
    {
        file.WriteLine(output.ReadLine());
    }

    // Read the rest
    file.Write(output.ReadToEnd());

    // flush to file
    file.Flush();
}

由于问题是输出缓冲区已满,因此 php 进程在等待发送其输出时停​​止,解决方案是在 c# 程序中异步读取输出。

class Program {
    protected static /* yeah, yeah, it's only an example */ StringBuilder output;
    static void Main(string[] args)
    {
        // Create the process
        var process = new System.Diagnostics.Process();
        process.EnableRaisingEvents = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.FileName = "php.exe";
        process.StartInfo.Arguments = "-f path\test.php mu b 0 0 pgsql://user:pass@x.x.x.x:5432/nominatim";
        process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        process.StartInfo.RedirectStandardOutput = true;

        output = new StringBuilder();
        process.OutputDataReceived += process_OutputDataReceived;

        // Start the process
        process.Start();
        process.BeginOutputReadLine();

        // Wait for the process to finish
        process.WaitForExit();

        Console.WriteLine("test");
        // <-- do something with Program.output here -->

        Console.ReadKey();
    }

    static void process_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
    {
        if (!String.IsNullOrEmpty(e.Data)) {
            // edit: oops the new-line/carriage-return characters are not "in" e.Data.....
            // this _might_ be a problem depending on the actual output.
            output.Append(e.Data);
            output.Append(Environment.NewLine);
        }
    }
}

另请参阅:https://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline%28v=vs.110%29.aspx