Skip to content

Commit 6baeb50

Browse files
Merge pull request #529 from Macro-Deck-App/517-win11-running-after-installation-does-not-respond
Fix crash on pipe timeout
2 parents cf8be48 + 95c7a92 commit 6baeb50

File tree

4 files changed

+70
-74
lines changed

4 files changed

+70
-74
lines changed

MacroDeck/MacroDeck.cs

+9-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
using SuchByte.MacroDeck.Language;
1818
using SuchByte.MacroDeck.Logging;
1919
using SuchByte.MacroDeck.Notifications;
20-
using SuchByte.MacroDeck.Pipes;
20+
using SuchByte.MacroDeck.Pipe;
2121
using SuchByte.MacroDeck.Plugins;
2222
using SuchByte.MacroDeck.Profiles;
2323
using SuchByte.MacroDeck.Properties;
@@ -266,23 +266,22 @@ public static void RestartMacroDeck(string parameters = "")
266266

267267
public static void ShowMainWindow()
268268
{
269-
if (SyncContext == null)
269+
if (SyncContext is null)
270270
{
271271
CreateMainForm();
272-
} else
272+
return;
273+
}
274+
275+
SyncContext.Send(_ =>
273276
{
274-
SyncContext.Send(o =>
275-
{
276-
CreateMainForm();
277-
}, null);
278-
}
277+
CreateMainForm();
278+
}, null);
279279
}
280280

281281
private static void CreateMainForm()
282282
{
283283
if (Application.OpenForms.OfType<MainWindow>().Any()
284-
&& _mainWindow.IsDisposed == false
285-
&& _mainWindow.IsHandleCreated)
284+
&& _mainWindow is { IsDisposed: false, IsHandleCreated: true })
286285
{
287286
if (_mainWindow.InvokeRequired)
288287
{

MacroDeck/Pipe/MacroDeckPipeClient.cs

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
using System.IO.Pipes;
22

3-
namespace SuchByte.MacroDeck.Pipes;
3+
namespace SuchByte.MacroDeck.Pipe;
44

5-
public class MacroDeckPipeClient
5+
public static class MacroDeckPipeClient
66
{
77

8-
internal static bool SendShowMainWindowMessage()
8+
internal static Task<bool> SendShowMainWindowMessage()
99
{
1010
return SendPipeMessage("show");
1111
}
1212

13-
14-
internal static bool SendPipeMessage(string message)
13+
private static async Task<bool> SendPipeMessage(string message)
1514
{
16-
var client = new NamedPipeClientStream("macrodeck");
17-
client.Connect(2000);
18-
if (client.IsConnected)
15+
try
1916
{
20-
var buffer = Encoding.ASCII.GetBytes(message);
21-
client.Write(buffer, 0, buffer.Length);
22-
client.Close();
23-
client.Dispose();
24-
return true;
17+
await using var client = new NamedPipeClientStream("macrodeck");
18+
await client.ConnectAsync(2000);
19+
if (client.IsConnected)
20+
{
21+
var bytes = Encoding.ASCII.GetBytes(message);
22+
client.Write(bytes, 0, bytes.Length);
23+
return true;
24+
}
2525
}
26-
26+
catch (TimeoutException)
27+
{
28+
// Ignore
29+
}
30+
2731
return false;
2832
}
2933

MacroDeck/Pipe/MacroDeckPipeServer.cs

+30-40
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,43 @@
1-
using System.IO.Pipes;
2-
using System.Threading;
1+
using System.IO;
2+
using System.IO.Pipes;
33
using SuchByte.MacroDeck.Logging;
44

5-
namespace SuchByte.MacroDeck.Pipes;
5+
namespace SuchByte.MacroDeck.Pipe;
66

7-
public delegate void DelegateMessage(string message);
87
public class MacroDeckPipeServer
98
{
10-
public static event DelegateMessage PipeMessage;
9+
public static event Action<string>? PipeMessage;
1110

12-
13-
private static void WaitForConnectionCallBack(IAsyncResult iar)
11+
public static void Initialize()
1412
{
15-
try
16-
{
17-
using var pipeServer = (NamedPipeServerStream)iar.AsyncState;
18-
pipeServer.EndWaitForConnection(iar);
19-
var buffer = new byte[255];
20-
pipeServer.Read(buffer, 0, 255);
21-
var stringData = Encoding.ASCII.GetString(buffer).Trim('\0');
22-
var t = new Thread(() => PipeMessage.Invoke(stringData));
23-
t.SetApartmentState(ApartmentState.STA);
24-
t.Start();
25-
pipeServer.Close();
26-
SpawnServerStream();
27-
}
28-
catch
29-
{
30-
}
13+
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server");
14+
Task.Run(async () => await HandleConnections().ConfigureAwait(false));
3115
}
3216

33-
private static void SpawnServerStream()
17+
private static async Task HandleConnections()
3418
{
35-
try
36-
{
37-
MacroDeckLogger.Trace(typeof(MacroDeckPipeServer), "Spawning new server stream...");
38-
var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
39-
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
40-
}
41-
catch (Exception ex)
19+
do
4220
{
43-
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
44-
}
45-
}
46-
47-
public static void Initialize()
48-
{
49-
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server");
50-
SpawnServerStream();
51-
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server complete");
21+
await using var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1);
22+
using var sr = new StreamReader(pipeServer);
23+
try
24+
{
25+
await pipeServer.WaitForConnectionAsync();
26+
pipeServer.WaitForPipeDrain();
27+
var result = await sr.ReadLineAsync();
28+
PipeMessage?.Invoke(result);
29+
}
30+
catch (Exception ex)
31+
{
32+
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
33+
}
34+
finally
35+
{
36+
if (pipeServer.IsConnected)
37+
{
38+
pipeServer.Disconnect();
39+
}
40+
}
41+
} while (true);
5242
}
5343
}

MacroDeck/Program.cs

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
using SuchByte.MacroDeck.Logging;
2-
using SuchByte.MacroDeck.Pipes;
32
using SuchByte.MacroDeck.Startup;
43
using System.Diagnostics;
5-
using System.Threading;
6-
using System.Windows.Forms;
7-
using SuchByte.MacroDeck.Server;
4+
using SuchByte.MacroDeck.Pipe;
85

96
namespace SuchByte.MacroDeck;
107

@@ -25,26 +22,32 @@ private static void Main(string[] args)
2522

2623

2724
var startParameters = StartParameters.ParseParameters(args);
28-
CheckRunningInstance(startParameters.IgnorePidCheck);
25+
CheckRunningInstance(startParameters.IgnorePidCheck).Wait();
2926

3027
ApplicationPaths.Initialize(startParameters.PortableMode);
3128

3229
MacroDeck.Start(startParameters);
3330
}
3431

35-
private static void CheckRunningInstance(int ignoredPid)
32+
private static async Task CheckRunningInstance(int ignoredPid)
3633
{
3734
var proc = Process.GetCurrentProcess();
38-
var processes = Process.GetProcessesByName(proc.ProcessName).Where(x => ignoredPid == 0 || x.Id != ignoredPid).ToArray();
39-
if (processes?.Length <= 1) return;
40-
if (MacroDeckPipeClient.SendShowMainWindowMessage())
35+
var processes = Process.GetProcessesByName(proc.ProcessName)
36+
.Where(x => ignoredPid == 0 || x.Id != ignoredPid)
37+
.ToArray();
38+
if (processes.Length <= 1)
39+
{
40+
return;
41+
}
42+
43+
if (await MacroDeckPipeClient.SendShowMainWindowMessage())
4144
{
4245
Environment.Exit(0);
4346
return;
4447
}
4548

4649
// Kill instance if no response
47-
foreach (var p in processes?.Where(x => x.Id != proc.Id) ?? Array.Empty<Process>())
50+
foreach (var p in processes.Where(x => x.Id != proc.Id))
4851
{
4952
try
5053
{

0 commit comments

Comments
 (0)