Fix crash on pipe timeout

This commit is contained in:
Manuel Mayer
2024-05-14 12:53:17 +02:00
parent 255ff36e4c
commit 95c7a9282b
4 changed files with 72 additions and 76 deletions

View File

@@ -17,7 +17,7 @@ using SuchByte.MacroDeck.Icons;
using SuchByte.MacroDeck.Language;
using SuchByte.MacroDeck.Logging;
using SuchByte.MacroDeck.Notifications;
using SuchByte.MacroDeck.Pipes;
using SuchByte.MacroDeck.Pipe;
using SuchByte.MacroDeck.Plugins;
using SuchByte.MacroDeck.Profiles;
using SuchByte.MacroDeck.Properties;
@@ -266,23 +266,22 @@ public class MacroDeck : NativeWindow
public static void ShowMainWindow()
{
if (SyncContext == null)
if (SyncContext is null)
{
CreateMainForm();
} else
return;
}
SyncContext.Send(_ =>
{
SyncContext.Send(o =>
{
CreateMainForm();
}, null);
}
CreateMainForm();
}, null);
}
private static void CreateMainForm()
{
if (Application.OpenForms.OfType<MainWindow>().Any()
&& _mainWindow.IsDisposed == false
&& _mainWindow.IsHandleCreated)
&& _mainWindow is { IsDisposed: false, IsHandleCreated: true })
{
if (_mainWindow.InvokeRequired)
{

View File

@@ -1,29 +1,33 @@
using System.IO.Pipes;
namespace SuchByte.MacroDeck.Pipes;
namespace SuchByte.MacroDeck.Pipe;
public class MacroDeckPipeClient
public static class MacroDeckPipeClient
{
internal static bool SendShowMainWindowMessage()
internal static Task<bool> SendShowMainWindowMessage()
{
return SendPipeMessage("show");
}
internal static bool SendPipeMessage(string message)
private static async Task<bool> SendPipeMessage(string message)
{
var client = new NamedPipeClientStream("macrodeck");
client.Connect(2000);
if (client.IsConnected)
try
{
var buffer = Encoding.ASCII.GetBytes(message);
client.Write(buffer, 0, buffer.Length);
client.Close();
client.Dispose();
return true;
await using var client = new NamedPipeClientStream("macrodeck");
await client.ConnectAsync(2000);
if (client.IsConnected)
{
var bytes = Encoding.ASCII.GetBytes(message);
client.Write(bytes, 0, bytes.Length);
return true;
}
}
catch (TimeoutException)
{
// Ignore
}
return false;
}

View File

@@ -1,53 +1,43 @@
using System.IO.Pipes;
using System.Threading;
using System.IO;
using System.IO.Pipes;
using SuchByte.MacroDeck.Logging;
namespace SuchByte.MacroDeck.Pipes;
namespace SuchByte.MacroDeck.Pipe;
public delegate void DelegateMessage(string message);
public class MacroDeckPipeServer
{
public static event DelegateMessage PipeMessage;
private static void WaitForConnectionCallBack(IAsyncResult iar)
{
try
{
using var pipeServer = (NamedPipeServerStream)iar.AsyncState;
pipeServer.EndWaitForConnection(iar);
var buffer = new byte[255];
pipeServer.Read(buffer, 0, 255);
var stringData = Encoding.ASCII.GetString(buffer).Trim('\0');
var t = new Thread(() => PipeMessage.Invoke(stringData));
t.SetApartmentState(ApartmentState.STA);
t.Start();
pipeServer.Close();
SpawnServerStream();
}
catch
{
}
}
private static void SpawnServerStream()
{
try
{
MacroDeckLogger.Trace(typeof(MacroDeckPipeServer), "Spawning new server stream...");
var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch (Exception ex)
{
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
}
}
public static event Action<string>? PipeMessage;
public static void Initialize()
{
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server");
SpawnServerStream();
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server complete");
Task.Run(async () => await HandleConnections().ConfigureAwait(false));
}
private static async Task HandleConnections()
{
do
{
await using var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1);
using var sr = new StreamReader(pipeServer);
try
{
await pipeServer.WaitForConnectionAsync();
pipeServer.WaitForPipeDrain();
var result = await sr.ReadLineAsync();
PipeMessage?.Invoke(result);
}
catch (Exception ex)
{
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
}
finally
{
if (pipeServer.IsConnected)
{
pipeServer.Disconnect();
}
}
} while (true);
}
}

View File

@@ -1,10 +1,7 @@
using SuchByte.MacroDeck.Logging;
using SuchByte.MacroDeck.Pipes;
using SuchByte.MacroDeck.Startup;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using SuchByte.MacroDeck.Server;
using SuchByte.MacroDeck.Pipe;
namespace SuchByte.MacroDeck;
@@ -25,26 +22,32 @@ internal class Program
var startParameters = StartParameters.ParseParameters(args);
CheckRunningInstance(startParameters.IgnorePidCheck);
CheckRunningInstance(startParameters.IgnorePidCheck).Wait();
ApplicationPaths.Initialize(startParameters.PortableMode);
MacroDeck.Start(startParameters);
}
private static void CheckRunningInstance(int ignoredPid)
private static async Task CheckRunningInstance(int ignoredPid)
{
var proc = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(proc.ProcessName).Where(x => ignoredPid == 0 || x.Id != ignoredPid).ToArray();
if (processes?.Length <= 1) return;
if (MacroDeckPipeClient.SendShowMainWindowMessage())
var processes = Process.GetProcessesByName(proc.ProcessName)
.Where(x => ignoredPid == 0 || x.Id != ignoredPid)
.ToArray();
if (processes.Length <= 1)
{
return;
}
if (await MacroDeckPipeClient.SendShowMainWindowMessage())
{
Environment.Exit(0);
return;
}
// Kill instance if no response
foreach (var p in processes?.Where(x => x.Id != proc.Id) ?? Array.Empty<Process>())
foreach (var p in processes.Where(x => x.Id != proc.Id))
{
try
{