首页 > 解决方案 > 在 IIS Express 停止后停止 npm 任务/脚本

问题描述

所以这是一个有趣的问题。我有一个使用 EntityFrameworkCore 和 VueJS 的 dotnetcore 3 项目。正确的。我Startup.cs:Configure(app,env)的声明如下:

app.UseSpa(spa =>
{
  if (env.IsDevelopment())
    spa.Options.SourcePath = "ClientApp";
  else
    spa.Options.SourcePath = "dist";

  if (env.IsDevelopment())
    {
      spa.UseVueCli(npmScript: "serve", port: 4444, forceKill: true);
    }
});

如您所见,我已手动指定端口,4444如果我不这样做,应用程序将尝试在端口上运行,8080或者8080++直到应用程序到达机器上的空闲端口。这适用于您只运行一次应用程序然后它从未崩溃或 Visual Studio 从未崩溃或您必须停止调试代码以管理项目文件结构的情况。你明白我的意思。在开发中你永远不会只只需触发一次命令并完成它。至少在我的经验中不是。

但尽管如此,这是此设置假设您所做的,因为当 IIS Express 服务关闭时它永远不会停止 npm-script,但它会尝试在同一 localhost 端口上重新启动 VueJS 应用程序,这确保与重新启动的应用程序的连接没有正确建立,因此会发生混乱。除非你通过 windows 终端杀死之前的 npm-script 任务。

所以我的问题是 - 当我停止我的 IIS Express 服务器时,有谁知道如何阻止脚本运行并杀死让它保持活动状态的任务?老实说,这对我来说有点莫名其妙:)

如果有人感兴趣的话,中间件类:)

#region Assembly VueCliMiddleware, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null
// C:\Users\<USER>\.nuget\packages\vueclimiddleware\3.1.1\lib\netcoreapp3.1\VueCliMiddleware.dll
#endregion

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.SpaServices;
using VueCliMiddleware;

namespace VueCliMiddleware
{
    public static class VueCliMiddlewareExtensions
    {
        public static IEndpointConventionBuilder MapToVueCliProxy(this IEndpointRouteBuilder endpoints, string pattern, SpaOptions options, string npmScript = "serve", int port = 8080, ScriptRunnerType runner = ScriptRunnerType.Npm, string regex = "running at", bool forceKill = false);
        public static IEndpointConventionBuilder MapToVueCliProxy(this IEndpointRouteBuilder endpoints, string pattern, string sourcePath, string npmScript = "serve", int port = 8080, ScriptRunnerType runner = ScriptRunnerType.Npm, string regex = "running at", bool forceKill = false);
        public static IEndpointConventionBuilder MapToVueCliProxy(this IEndpointRouteBuilder endpoints, SpaOptions options, string npmScript = "serve", int port = 8080, ScriptRunnerType runner = ScriptRunnerType.Npm, string regex = "running at", bool forceKill = false);
        public static IEndpointConventionBuilder MapToVueCliProxy(this IEndpointRouteBuilder endpoints, string sourcePath, string npmScript = "serve", int port = 8080, ScriptRunnerType runner = ScriptRunnerType.Npm, string regex = "running at", bool forceKill = false);
        public static void UseVueCli(this ISpaBuilder spaBuilder, string npmScript = "serve", int port = 8080, ScriptRunnerType runner = ScriptRunnerType.Npm, string regex = "running at", bool forceKill = false);
    }
}

标签: c#node.js.net-corenpm-scripts

解决方案


好的,免责声明:这完全是 hack,只有在您事先知道您的端口时才有效(至少,它适用于我的机器;)),需要大量重构,我不提供任何保证。

很少有人知道您可以在 Startup 类中轻松附加到应用程序生命周期:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        lifetime.ApplicationStopping.Register(OnStopping); // <== Magic is here!
    }
    // [Blah blah, yada yada, your super cool code here]
}

private void OnStopping()
{
    // Things to do before application is stopped
}

我的想法是让你的known tcp port(比方说4444)和kill it(戏剧音乐)听的过程。

我知道从端口检索 PID 的更快方法是使用netstat -nao. OnStopping 代码将如下所示:

private void OnStopping()
{
    // Following code runs on Windows platform only, 
    // if current platform is something else, we just exit
    if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return;

    Process netstat = new Process();
    netstat.StartInfo = new ProcessStartInfo
    {
        FileName = "netstat",
        Arguments = "-nao",
        RedirectStandardOutput = true
    };

    netstat.Start();
    var output = netstat.StandardOutput.ReadToEnd();
    var ports = output.Split('\n');
    var f = ports.FirstOrDefault(p => p.Contains("LISTENING") && p.Contains("127.0.0.1:4444"));
    var pid = int.Parse(f.Split(' ').Last());
    var clientServer = Process.GetProcessById(pid);
    clientServer.Kill();
    clientServer.WaitForExit();
}

请让我知道您的想法,以及它是否适合您。


推荐阅读