Skip to content

Commit be8a49e

Browse files
authored
Single instance mode (#274)
1 parent e4c5e05 commit be8a49e

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

src/10-Core/Wtq/Services/IPlatformService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ public interface IPlatformService
9090
/// </summary>
9191
bool IsCallable(string? workingDirectory, string fileName);
9292

93+
/// <summary>
94+
/// Returns whether another WTQ process is running, used to prevent multiple WTQ instances.
95+
/// </summary>
96+
bool IsWtqRunning();
97+
9398
/// <summary>
9499
/// Opens the specified <paramref name="path"/> using the default application (e.g. usually Explorer on Windows).
95100
/// </summary>

src/10-Core/Wtq/Services/PlatformServiceBase.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,24 @@ public virtual bool IsCallable(string? workingDirectory, string fileName)
230230
return ExecutableExtensions.Any(ex => ResolvePath(fileName + ex) != null);
231231
}
232232

233+
/// <inheritdoc/>
234+
public virtual bool IsWtqRunning()
235+
{
236+
// Get a reference to this process, so we can filter it out when looking for other processes.
237+
var self = Process.GetCurrentProcess();
238+
239+
// Look for other WTQ processes.
240+
var otherWtq = Process.GetProcessesByName(self.ProcessName).FirstOrDefault(p => p.Id != self.Id);
241+
242+
if (otherWtq != null)
243+
{
244+
Log.LogWarning("Found other WTQ process (PID:{Pid})", otherWtq.Id);
245+
return true;
246+
}
247+
248+
return false;
249+
}
250+
233251
/// <inheritdoc/>
234252
public virtual bool ShouldUsePollingFileWatcherForPath(string path)
235253
{

src/10-Core/Wtq/Services/WtqHost.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@ public class WtqHost
1515
private static readonly TimeSpan DisposeTimeout = TimeSpan.FromSeconds(3);
1616

1717
private static readonly ILogger _log = Utils.Log.For<WtqHost>();
18+
private readonly JoinableTaskFactory _taskFactory = new(JoinableTaskContext.CreateNoOpContext());
1819

1920
private readonly IEnumerable<IHostedService> _hostedServices;
20-
private readonly JoinableTaskFactory _taskFactory = new(JoinableTaskContext.CreateNoOpContext());
21+
private readonly IPlatformService _platformService;
2122

2223
public WtqHost(
2324
IHostApplicationLifetime appLifetime,
2425
IEnumerable<IHostedService> hostedServices,
26+
IPlatformService platformService,
2527
Action onExit)
2628
{
2729
_ = Guard.Against.Null(appLifetime);
2830
_ = Guard.Against.Null(onExit);
2931
_hostedServices = Guard.Against.Null(hostedServices);
32+
_platformService = Guard.Against.Null(platformService);
3033

3134
// Initializing + Starting
3235
_ = appLifetime.ApplicationStarted.Register(() =>
@@ -54,6 +57,12 @@ public WtqHost(
5457

5558
private async Task InitAsync()
5659
{
60+
if (_platformService.IsWtqRunning())
61+
{
62+
_log.LogWarning("WTQ seems to already be running. Running multiple instances can cause some really weird behavior, so I'm stopping this instance. If you don't see another instance already running, try killing all WTQ processes and start again.");
63+
Environment.Exit(-1);
64+
}
65+
5766
var sw1 = Stopwatch.StartNew();
5867

5968
_log.LogDebug("Initializing services");

src/20-Services/Wtq.Services.UI/WtqUIHostBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public static void Run(Action<IServiceCollection> services)
5353
_ = new WtqHost(
5454
lifetime,
5555
app.Services.GetRequiredService<IEnumerable<IHostedService>>(),
56+
app.Services.GetRequiredService<IPlatformService>(),
5657
() => ui.Exit());
5758

5859
lifetime.NotifyStarted();

0 commit comments

Comments
 (0)