前后台同时启动的方式
目的:希望在WPF前台启动后,带动 ASP.NET Core 后台服务一同启动,在前台关闭后,也一起关闭
方法:在打开窗口之前,首先手动打开 ASP.NET Core 子进程,然后注册窗口关闭回调,通知后台关闭进程
public static class ExternalProcessFactory
{
private static Process Process;
public static Process GetApp()
{
if (Process != null)
{
return Process;
}
Process process = new Process();
//var app = Environment.CurrentDirectory + "/xxx.exe";
var app = "D:\\xxx.exe";
process.StartInfo.FileName = app;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = false;
process.StartInfo.RedirectStandardError = false;
process.StartInfo.RedirectStandardInput = false;
process.StartInfo.CreateNoWindow = false;
//process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
process.StartInfo.WorkingDirectory = "D:\\workspace";
Process = process;
return process;
}
public static void Close(int? timeoutMilliseconds = null)
{
if (Process == null || Process.HasExited)
{
return;
}
if (AttachConsole((uint)Process.Id))
{
SetConsoleCtrlHandler(null, true);
GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);
FreeConsole();
if (timeoutMilliseconds != null)
{
Process.WaitForExit(timeoutMilliseconds.Value);
}
else
{
Process.WaitForExit();
}
SetConsoleCtrlHandler(null, false);
}
}
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll")]
private static extern bool FreeConsole();
[DllImport("kernel32.dll")]
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);
enum CtrlTypes : uint
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
private delegate bool ConsoleCtrlDelegate(CtrlTypes ctrlTypes);
}
大部分代码都是查询了如何发送 CTRL_C 信号给控制台应用,使得可以优雅关闭的代码,剩下的只需要编写创建子进程的部分,我们需要填充一些子进程的基本信息
- CreateNoWindow,如果不需要子进程打开窗口,而是后台运行,可以设置为 true
- WorkingDirectory,这个比较重要,如果不设置启动的环境,可能会出现配置文件读取不成功的问题
- FileName,我是直接将两个项目发布到同一个文件夹下,所以只需要
Environment.CurrentDirectory
就可以找到了