在 IIS Express 停止后停止 npm task/script
Stop npm task/script, after IIS Express stop
所以这很有趣。我有一个使用 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
或 [=16] =] 直到应用程序命中机器上的空闲端口。当您只 运行 应用程序一次然后它永远不会崩溃或 Visual Studio 永远不会崩溃或者您必须停止调试代码以管理项目文件结构时,这是可以的。.你明白我的意思.. 在开发中,您永远不会只触发一次命令并完成它。至少在我的经验中不是。
但是,尽管如此,这就是此设置假定您所做的,因为当 IIS Express 服务关闭时它永远不会停止 npm 脚本,但它会尝试重新启动 VueJS 应用程序,在我的例子中,在同一时间本地主机端口,它确保没有正确建立与重新启动的应用程序的连接,从而导致混乱。除非你通过 windows 终端杀死之前的 npm-script 任务。
所以我的问题是 - 当我停止我的 IIS Express 服务器时,有人知道如何从 运行 停止脚本并终止使它保持活动状态的任务吗?老实说,这让我有点莫名其妙:)
中间件class如果有人感兴趣:)
#region Assembly VueCliMiddleware, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null
// C:\Users\<USER>\.nuget\packages\vueclimiddleware.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);
}
}
好的,免责声明:这是一个彻头彻尾的 hack,只有当你事先知道你的端口时才有效(至少,它在我的机器上有效 ;) ),需要 HEAVY 重构,我不提供任何保证。
很少有人知道您可以非常轻松地附加到您的应用程序生命周期,在启动 class:
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();
}
请告诉我您的想法,以及它是否适合您。
以下:
if (portNumber < 80)
{
portNumber = TcpPortFinder.FindAvailablePort();
}
else
{
// if the port we want to use is occupied, terminate the process utilizing that port.
// this occurs when "stop" is used from the debugger and the middleware does not have the opportunity to kill the process
PidUtils.KillPort((ushort)portNumber, forceKill);
}
您可以在本地构建它,然后进行跟踪以查看 if/why 它没有按预期工作。似乎 forceKill 的全部意义在于解决这个问题。
所以这很有趣。我有一个使用 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
或 [=16] =] 直到应用程序命中机器上的空闲端口。当您只 运行 应用程序一次然后它永远不会崩溃或 Visual Studio 永远不会崩溃或者您必须停止调试代码以管理项目文件结构时,这是可以的。.你明白我的意思.. 在开发中,您永远不会只触发一次命令并完成它。至少在我的经验中不是。
但是,尽管如此,这就是此设置假定您所做的,因为当 IIS Express 服务关闭时它永远不会停止 npm 脚本,但它会尝试重新启动 VueJS 应用程序,在我的例子中,在同一时间本地主机端口,它确保没有正确建立与重新启动的应用程序的连接,从而导致混乱。除非你通过 windows 终端杀死之前的 npm-script 任务。
所以我的问题是 - 当我停止我的 IIS Express 服务器时,有人知道如何从 运行 停止脚本并终止使它保持活动状态的任务吗?老实说,这让我有点莫名其妙:)
中间件class如果有人感兴趣:)
#region Assembly VueCliMiddleware, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null
// C:\Users\<USER>\.nuget\packages\vueclimiddleware.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);
}
}
好的,免责声明:这是一个彻头彻尾的 hack,只有当你事先知道你的端口时才有效(至少,它在我的机器上有效 ;) ),需要 HEAVY 重构,我不提供任何保证。
很少有人知道您可以非常轻松地附加到您的应用程序生命周期,在启动 class:
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();
}
请告诉我您的想法,以及它是否适合您。
以下:
if (portNumber < 80)
{
portNumber = TcpPortFinder.FindAvailablePort();
}
else
{
// if the port we want to use is occupied, terminate the process utilizing that port.
// this occurs when "stop" is used from the debugger and the middleware does not have the opportunity to kill the process
PidUtils.KillPort((ushort)portNumber, forceKill);
}
您可以在本地构建它,然后进行跟踪以查看 if/why 它没有按预期工作。似乎 forceKill 的全部意义在于解决这个问题。