C#:调用一个php脚本并能够阻止它

本文关键字:脚本 php 一个 调用 | 更新日期: 2023-09-27 18:32:13

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

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

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

我无法将超时设置为 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 不返回似乎是不可重现的。当我测试不同的脚本(没有参数)时,它可以工作,可能是脚本或参数的传递。

从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();
}

C#:调用一个php脚本并能够阻止它

由于问题是输出缓冲区已满,因此 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