mirror of
https://github.com/Macro-Deck-App/Macro-Deck.git
synced 2026-05-06 21:51:04 +08:00
Fix crash on pipe timeout
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user