2024-02-16 04:06:19 +00:00
|
|
|
|
#nullable enable
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
2023-07-03 08:44:50 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.IO.Pipelines;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Flow.Launcher.Infrastructure;
|
|
|
|
|
|
using Flow.Launcher.Plugin;
|
2024-02-06 19:07:21 +00:00
|
|
|
|
using Meziantou.Framework.Win32;
|
2024-02-16 04:06:19 +00:00
|
|
|
|
using Microsoft.VisualBasic.ApplicationServices;
|
2023-07-03 08:44:50 +00:00
|
|
|
|
using Nerdbank.Streams;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Flow.Launcher.Core.Plugin
|
|
|
|
|
|
{
|
|
|
|
|
|
internal abstract class ProcessStreamPluginV2 : JsonRPCPluginV2
|
|
|
|
|
|
{
|
2024-02-06 19:07:21 +00:00
|
|
|
|
private static JobObject _jobObject = new JobObject();
|
|
|
|
|
|
|
|
|
|
|
|
static ProcessStreamPluginV2()
|
|
|
|
|
|
{
|
|
|
|
|
|
_jobObject.SetLimits(new JobObjectLimits()
|
|
|
|
|
|
{
|
2024-02-16 04:06:19 +00:00
|
|
|
|
Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException |
|
|
|
|
|
|
JobObjectLimitFlags.SilentBreakawayOk
|
2024-02-06 19:07:21 +00:00
|
|
|
|
});
|
2024-02-16 04:06:19 +00:00
|
|
|
|
|
2024-02-06 19:07:21 +00:00
|
|
|
|
_jobObject.AssignProcess(Process.GetCurrentProcess());
|
|
|
|
|
|
}
|
2023-07-03 08:44:50 +00:00
|
|
|
|
|
2024-02-16 04:06:19 +00:00
|
|
|
|
protected sealed override IDuplexPipe ClientPipe { get; set; } = null!;
|
2023-07-03 08:44:50 +00:00
|
|
|
|
|
|
|
|
|
|
protected abstract ProcessStartInfo StartInfo { get; set; }
|
|
|
|
|
|
|
2024-02-16 04:06:19 +00:00
|
|
|
|
protected Process ClientProcess { get; set; } = null!;
|
2023-07-03 08:44:50 +00:00
|
|
|
|
|
|
|
|
|
|
public override async Task InitAsync(PluginInitContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
StartInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version;
|
|
|
|
|
|
StartInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
|
|
|
|
|
|
StartInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
|
|
|
|
|
|
|
2024-02-16 04:06:19 +00:00
|
|
|
|
StartInfo.RedirectStandardError = true;
|
|
|
|
|
|
StartInfo.RedirectStandardInput = true;
|
|
|
|
|
|
StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
|
StartInfo.CreateNoWindow = true;
|
|
|
|
|
|
StartInfo.UseShellExecute = false;
|
2023-07-03 08:44:50 +00:00
|
|
|
|
StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
|
|
|
|
|
|
|
2024-02-16 04:06:19 +00:00
|
|
|
|
var process = Process.Start(StartInfo);
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(process);
|
|
|
|
|
|
ClientProcess = process;
|
|
|
|
|
|
_jobObject.AssignProcess(ClientProcess);
|
|
|
|
|
|
|
2023-07-03 08:44:50 +00:00
|
|
|
|
SetupPipe(ClientProcess);
|
|
|
|
|
|
|
2023-11-26 15:33:34 +00:00
|
|
|
|
ErrorStream = ClientProcess.StandardError;
|
|
|
|
|
|
|
2023-07-03 08:44:50 +00:00
|
|
|
|
await base.InitAsync(context);
|
|
|
|
|
|
}
|
2024-02-06 19:07:21 +00:00
|
|
|
|
|
2023-07-03 08:44:50 +00:00
|
|
|
|
private void SetupPipe(Process process)
|
|
|
|
|
|
{
|
|
|
|
|
|
var (reader, writer) = (PipeReader.Create(process.StandardOutput.BaseStream),
|
|
|
|
|
|
PipeWriter.Create(process.StandardInput.BaseStream));
|
|
|
|
|
|
ClientPipe = new DuplexPipe(reader, writer);
|
|
|
|
|
|
}
|
2024-02-06 19:07:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-07-03 08:44:50 +00:00
|
|
|
|
public override async Task ReloadDataAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
var oldProcess = ClientProcess;
|
|
|
|
|
|
ClientProcess = Process.Start(StartInfo);
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(ClientProcess);
|
|
|
|
|
|
SetupPipe(ClientProcess);
|
|
|
|
|
|
await base.ReloadDataAsync();
|
|
|
|
|
|
oldProcess.Kill(true);
|
|
|
|
|
|
await oldProcess.WaitForExitAsync();
|
|
|
|
|
|
oldProcess.Dispose();
|
|
|
|
|
|
}
|
2024-02-06 19:07:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-07-03 08:44:50 +00:00
|
|
|
|
public override async ValueTask DisposeAsync()
|
|
|
|
|
|
{
|
2024-06-06 00:29:24 +00:00
|
|
|
|
await base.DisposeAsync();
|
2023-07-03 08:44:50 +00:00
|
|
|
|
ClientProcess.Kill(true);
|
|
|
|
|
|
await ClientProcess.WaitForExitAsync();
|
|
|
|
|
|
ClientProcess.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|