1
1
using System ;
2
2
using System . IO ;
3
3
using System . Runtime . Versioning ;
4
+ using System . Threading ;
4
5
5
6
using Avalonia ;
6
7
using Avalonia . ReactiveUI ;
13
14
namespace TwitchStreamingTools ;
14
15
15
16
internal sealed class Program {
17
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
18
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
19
+ // yet and stuff might break.
20
+
21
+ /// <summary>
22
+ /// The name used to ensure only a single instance of the application is running.
23
+ /// </summary>
24
+ private const string MutexName = "TwitchStreamingTools_SingleInstance" ;
25
+
16
26
/// <summary>
17
27
/// The logger.
18
28
/// </summary>
19
29
private static readonly ILog Log = LogManager . GetLogger ( typeof ( Program ) ) ;
20
30
21
- // Initialization code. Don't use any Avalonia, third-party APIs or any
22
- // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
23
- // yet and stuff might break.
31
+ /// <summary>
32
+ /// Used to prevent multiple instances of the application from running.
33
+ /// </summary>
34
+ private static Mutex ? _mutex ;
24
35
25
36
/// <summary>
26
37
/// Main entrypoint of the application.
@@ -31,7 +42,7 @@ public static void Main(string[] args) {
31
42
#if DEBUG
32
43
XmlConfigurator . Configure ( new FileInfo ( "log4net.debug.config" ) ) ;
33
44
#else
34
- XmlConfigurator . Configure ( new FileInfo ( "log4net.config" ) ) ;
45
+ XmlConfigurator . Configure ( new FileInfo ( "log4net.config" ) ) ;
35
46
#endif
36
47
37
48
Log . Info ( "Started application" ) ;
@@ -40,11 +51,24 @@ public static void Main(string[] args) {
40
51
Log . Fatal ( "Unhandled exception" , exceptArgs . ExceptionObject as Exception ) ;
41
52
} ;
42
53
43
- BuildAvaloniaApp ( )
44
- . StartWithClassicDesktopLifetime ( args ) ;
45
- }
54
+ // We only allow a single instance of the application to be launched at once (due to having only a single config
55
+ // file)
56
+ _mutex = new Mutex ( true , MutexName , out bool onlyAppInstance ) ;
57
+ if ( ! onlyAppInstance ) {
58
+ Log . Info ( "Application instance already running. Exiting." ) ;
59
+ return ;
60
+ }
46
61
47
- // Avalonia configuration, don't remove; also used by visual designer.
62
+ try {
63
+ BuildAvaloniaApp ( )
64
+ . StartWithClassicDesktopLifetime ( args ) ;
65
+ }
66
+ finally {
67
+ // Release the mutex when the application exits
68
+ _mutex . ReleaseMutex ( ) ;
69
+ _mutex . Dispose ( ) ;
70
+ }
71
+ }
48
72
49
73
/// <summary>
50
74
/// Builds the avalonia application.
0 commit comments