63 lines
2.1 KiB
C#
63 lines
2.1 KiB
C#
using System.IO.Pipes;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace Lumi.Companion.App;
|
|
|
|
internal sealed class SingleInstanceCoordinator : IDisposable
|
|
{
|
|
private readonly Mutex _mutex;
|
|
private readonly CancellationTokenSource _lifetime = new();
|
|
private readonly string _pipeName;
|
|
private Task? _listener;
|
|
|
|
public SingleInstanceCoordinator()
|
|
{
|
|
var userKey = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes($"{Environment.UserDomainName}\\{Environment.UserName}"))).Substring(0, 16);
|
|
_pipeName = $"Lumi.Companion.Activate.v1.{userKey}";
|
|
_mutex = new Mutex(true, $"Local\\Lumi.Companion.v1.{userKey}", out var created);
|
|
IsPrimary = created;
|
|
if (created) _listener = Task.Run(() => ListenAsync(_lifetime.Token));
|
|
}
|
|
|
|
public bool IsPrimary { get; }
|
|
public event Action? ActivationRequested;
|
|
|
|
public void SignalPrimary()
|
|
{
|
|
try
|
|
{
|
|
using var pipe = new NamedPipeClientStream(".", _pipeName, PipeDirection.Out, PipeOptions.Asynchronous);
|
|
pipe.Connect(1000);
|
|
pipe.WriteByte(1);
|
|
pipe.Flush();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private async Task ListenAsync(CancellationToken cancellationToken)
|
|
{
|
|
while (!cancellationToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
await using var pipe = new NamedPipeServerStream(_pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte,
|
|
PipeOptions.Asynchronous | PipeOptions.CurrentUserOnly, 1, 1);
|
|
await pipe.WaitForConnectionAsync(cancellationToken);
|
|
if (pipe.ReadByte() == 1) ActivationRequested?.Invoke();
|
|
}
|
|
catch (OperationCanceledException) { break; }
|
|
catch when (!cancellationToken.IsCancellationRequested) { await Task.Delay(200, cancellationToken); }
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_lifetime.Cancel();
|
|
try { _listener?.Wait(500); } catch { }
|
|
if (IsPrimary) try { _mutex.ReleaseMutex(); } catch { }
|
|
_mutex.Dispose();
|
|
_lifetime.Dispose();
|
|
}
|
|
}
|