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);
}
}
}
我目前正在开发一个 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);
}
}
}