【发布时间】:2018-04-18 20:18:51
【问题描述】:
我要解决什么问题
为了改进我的构建管道,我想添加一个端到端测试步骤。我计划通过 CLI 工具(.NET“控制台应用程序”)来实现它。该工具将启动并编排一些npm/node 命令(进程)。
更具体地说,会有:
- 一个后端进程;
- 一个前端进程;
- 和一个测试过程。
当测试进程 (3) 完成时,CLI 工具应该优雅地终止后端 (1) 和前端 (2) 进程,如果 则返回 0 退出代码每个编排的进程都已成功终止。
麻烦
在下面的Minimal, Complete, and Verifiable example 中,我试图启动一个进程serviceAlikeProcess 和一个失败的进程(brokenWithErrorProcess)。当后一个失败时,我试图通过Kill(process)方法强制终止前一个。
!!! 因为它是suggested here,所以node/npm 进程正在通过cmd 进程启动。 IE。我首先启动了一个cmd 进程,然后将node test.js 写入其stdin 流。 node 进程启动得很好,但是当 cmd 进程稍后终止时,node 进程继续运行并产生输出。
我想这是因为 cmd 和 node 进程没有以父子关系链接(因为如果我从任务中手动终止 cmd 进程经理,我观察到完全相同的行为)。
问题
如何可靠地终止这两个进程?
想法:我正在考虑捕获node进程'pid,然后自己终止cmd和node进程,但我还没有找到捕获的方法那pid...
代码
程序.cs
using System;
using System.Diagnostics;
using System.IO;
namespace RunE2E
{
public class Program
{
static string currentDirectory = Directory.GetCurrentDirectory();
public static int Main(string[] args)
{
var serviceAlikeProcess = StartProcessViaCmd("node", "test.js", "");
var brokenWithErrorProcess = StartProcessViaCmd("npm", "THIS IS NOT A REAL COMMAND, THEREFORE EXPECTED TO FAIL", "");
brokenWithErrorProcess.Exited += (_, __) => KillProcess(serviceAlikeProcess);
serviceAlikeProcess.WaitForExit();
return serviceAlikeProcess.ExitCode;
}
private static Process StartProcessViaCmd(string command, string arguments, string workingDirectory)
{
workingDirectory = NormalizeWorkingDirectory(workingDirectory);
var process = new Process
{
EnableRaisingEvents = true,
StartInfo = new ProcessStartInfo
{
FileName = "cmd",
Arguments = arguments,
WorkingDirectory = workingDirectory,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
}
};
process.ErrorDataReceived += (_, e) => handle(command, arguments, workingDirectory, "ERROR", e.Data);
process.OutputDataReceived += (_, e) => handle(command, arguments, workingDirectory, "OUTPUT", e.Data);
try
{
Console.WriteLine($"[{workingDirectory}] {command} {arguments}");
var _ = process.Start();
process.BeginOutputReadLine();
process.StandardInput.WriteLine($"{command} {arguments} & exit");
}
catch (Exception exc)
{
Console.WriteLine($"[{workingDirectory}] {command} {arguments} : {exc}");
throw;
}
return process;
}
static string NormalizeWorkingDirectory(string workingDirectory)
{
if (string.IsNullOrWhiteSpace(workingDirectory))
return currentDirectory;
else if (Path.IsPathRooted(workingDirectory))
return workingDirectory;
else
return Path.GetFullPath(Path.Combine(currentDirectory, workingDirectory));
}
static Action<string, string, string, string, string> handle =
(string command, string arguments, string workingDirectory, string level, string message) =>
Console.WriteLine($"[{workingDirectory}] {command} {arguments} {level}: {message}");
static void KillProcess(Process process)
{
if (process != null && !process.HasExited)
process.Kill();
}
}
}
test.js
setInterval(() => {
console.info(new Date());
}, 1000);
截图
在以编程方式启动任何进程之前
`cmd`进程被杀死后
控制台输出
【问题讨论】:
标签: c# .net node.js cmd .net-core