Skip to content

Commit 48792b6

Browse files
committed
Restore style
1 parent 9d81e60 commit 48792b6

File tree

1 file changed

+113
-112
lines changed

1 file changed

+113
-112
lines changed

Flow.Launcher/Helper/SingleInstance.cs

Lines changed: 113 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -6,137 +6,138 @@
66

77
// http://blogs.microsoft.co.il/arik/2010/05/28/wpf-single-instance-application/
88
// modified to allow single instace restart
9-
namespace Flow.Launcher.Helper;
10-
11-
public interface ISingleInstanceApp
12-
{
13-
void OnSecondAppStarted();
14-
}
15-
16-
/// <summary>
17-
/// This class checks to make sure that only one instance of
18-
/// this application is running at a time.
19-
/// </summary>
20-
/// <remarks>
21-
/// Note: this class should be used with some caution, because it does no
22-
/// security checking. For example, if one instance of an app that uses this class
23-
/// is running as Administrator, any other instance, even if it is not
24-
/// running as Administrator, can activate it with command line arguments.
25-
/// For most apps, this will not be much of an issue.
26-
/// </remarks>
27-
public static class SingleInstance<TApplication> where TApplication: Application, ISingleInstanceApp
9+
namespace Flow.Launcher.Helper
2810
{
29-
#region Private Fields
30-
31-
/// <summary>
32-
/// String delimiter used in channel names.
33-
/// </summary>
34-
private const string Delimiter = ":";
35-
36-
/// <summary>
37-
/// Suffix to the channel name.
38-
/// </summary>
39-
private const string ChannelNameSuffix = "SingeInstanceIPCChannel";
40-
private const string InstanceMutexName = "Flow.Launcher_Unique_Application_Mutex";
41-
42-
/// <summary>
43-
/// Application mutex.
44-
/// </summary>
45-
internal static Mutex SingleInstanceMutex { get; set; }
46-
47-
#endregion
48-
49-
#region Public Methods
11+
public interface ISingleInstanceApp
12+
{
13+
void OnSecondAppStarted();
14+
}
5015

5116
/// <summary>
52-
/// Checks if the instance of the application attempting to start is the first instance.
53-
/// If not, activates the first instance.
17+
/// This class checks to make sure that only one instance of
18+
/// this application is running at a time.
5419
/// </summary>
55-
/// <returns>True if this is the first instance of the application.</returns>
56-
public static bool InitializeAsFirstInstance()
20+
/// <remarks>
21+
/// Note: this class should be used with some caution, because it does no
22+
/// security checking. For example, if one instance of an app that uses this class
23+
/// is running as Administrator, any other instance, even if it is not
24+
/// running as Administrator, can activate it with command line arguments.
25+
/// For most apps, this will not be much of an issue.
26+
/// </remarks>
27+
public static class SingleInstance<TApplication> where TApplication : Application, ISingleInstanceApp
5728
{
58-
// Build unique application Id and the IPC channel name.
59-
string applicationIdentifier = InstanceMutexName + Environment.UserName;
60-
61-
string channelName = string.Concat(applicationIdentifier, Delimiter, ChannelNameSuffix);
62-
63-
// Create mutex based on unique application Id to check if this is the first instance of the application.
64-
SingleInstanceMutex = new Mutex(true, applicationIdentifier, out var firstInstance);
65-
if (firstInstance)
29+
#region Private Fields
30+
31+
/// <summary>
32+
/// String delimiter used in channel names.
33+
/// </summary>
34+
private const string Delimiter = ":";
35+
36+
/// <summary>
37+
/// Suffix to the channel name.
38+
/// </summary>
39+
private const string ChannelNameSuffix = "SingeInstanceIPCChannel";
40+
private const string InstanceMutexName = "Flow.Launcher_Unique_Application_Mutex";
41+
42+
/// <summary>
43+
/// Application mutex.
44+
/// </summary>
45+
internal static Mutex SingleInstanceMutex { get; set; }
46+
47+
#endregion
48+
49+
#region Public Methods
50+
51+
/// <summary>
52+
/// Checks if the instance of the application attempting to start is the first instance.
53+
/// If not, activates the first instance.
54+
/// </summary>
55+
/// <returns>True if this is the first instance of the application.</returns>
56+
public static bool InitializeAsFirstInstance()
6657
{
67-
_ = CreateRemoteServiceAsync(channelName);
68-
return true;
58+
// Build unique application Id and the IPC channel name.
59+
string applicationIdentifier = InstanceMutexName + Environment.UserName;
60+
61+
string channelName = string.Concat(applicationIdentifier, Delimiter, ChannelNameSuffix);
62+
63+
// Create mutex based on unique application Id to check if this is the first instance of the application.
64+
SingleInstanceMutex = new Mutex(true, applicationIdentifier, out var firstInstance);
65+
if (firstInstance)
66+
{
67+
_ = CreateRemoteServiceAsync(channelName);
68+
return true;
69+
}
70+
else
71+
{
72+
_ = SignalFirstInstanceAsync(channelName);
73+
return false;
74+
}
6975
}
70-
else
76+
77+
/// <summary>
78+
/// Cleans up single-instance code, clearing shared resources, mutexes, etc.
79+
/// </summary>
80+
public static void Cleanup()
7181
{
72-
_ = SignalFirstInstanceAsync(channelName);
73-
return false;
82+
SingleInstanceMutex?.ReleaseMutex();
7483
}
75-
}
7684

77-
/// <summary>
78-
/// Cleans up single-instance code, clearing shared resources, mutexes, etc.
79-
/// </summary>
80-
public static void Cleanup()
81-
{
82-
SingleInstanceMutex?.ReleaseMutex();
83-
}
85+
#endregion
8486

85-
#endregion
87+
#region Private Methods
8688

87-
#region Private Methods
88-
89-
/// <summary>
90-
/// Creates a remote server pipe for communication.
91-
/// Once receives signal from client, will activate first instance.
92-
/// </summary>
93-
/// <param name="channelName">Application's IPC channel name.</param>
94-
private static async Task CreateRemoteServiceAsync(string channelName)
95-
{
96-
using NamedPipeServerStream pipeServer = new NamedPipeServerStream(channelName, PipeDirection.In);
97-
while (true)
89+
/// <summary>
90+
/// Creates a remote server pipe for communication.
91+
/// Once receives signal from client, will activate first instance.
92+
/// </summary>
93+
/// <param name="channelName">Application's IPC channel name.</param>
94+
private static async Task CreateRemoteServiceAsync(string channelName)
9895
{
99-
// Wait for connection to the pipe
100-
await pipeServer.WaitForConnectionAsync();
101-
102-
// Do an asynchronous call to ActivateFirstInstance function
103-
Application.Current?.Dispatcher.Invoke(ActivateFirstInstance);
104-
105-
// Disconect client
106-
pipeServer.Disconnect();
96+
using NamedPipeServerStream pipeServer = new NamedPipeServerStream(channelName, PipeDirection.In);
97+
while (true)
98+
{
99+
// Wait for connection to the pipe
100+
await pipeServer.WaitForConnectionAsync();
101+
102+
// Do an asynchronous call to ActivateFirstInstance function
103+
Application.Current?.Dispatcher.Invoke(ActivateFirstInstance);
104+
105+
// Disconect client
106+
pipeServer.Disconnect();
107+
}
107108
}
108-
}
109109

110-
/// <summary>
111-
/// Creates a client pipe and sends a signal to server to launch first instance
112-
/// </summary>
113-
/// <param name="channelName">Application's IPC channel name.</param>
114-
/// <param name="args">
115-
/// Command line arguments for the second instance, passed to the first instance to take appropriate action.
116-
/// </param>
117-
private static async Task SignalFirstInstanceAsync(string channelName)
118-
{
119-
// Create a client pipe connected to server
120-
using NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", channelName, PipeDirection.Out);
110+
/// <summary>
111+
/// Creates a client pipe and sends a signal to server to launch first instance
112+
/// </summary>
113+
/// <param name="channelName">Application's IPC channel name.</param>
114+
/// <param name="args">
115+
/// Command line arguments for the second instance, passed to the first instance to take appropriate action.
116+
/// </param>
117+
private static async Task SignalFirstInstanceAsync(string channelName)
118+
{
119+
// Create a client pipe connected to server
120+
using NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", channelName, PipeDirection.Out);
121121

122-
// Connect to the available pipe
123-
await pipeClient.ConnectAsync(0);
124-
}
122+
// Connect to the available pipe
123+
await pipeClient.ConnectAsync(0);
124+
}
125125

126-
/// <summary>
127-
/// Activates the first instance of the application with arguments from a second instance.
128-
/// </summary>
129-
/// <param name="args">List of arguments to supply the first instance of the application.</param>
130-
private static void ActivateFirstInstance()
131-
{
132-
// Set main window state and process command line args
133-
if (Application.Current == null)
126+
/// <summary>
127+
/// Activates the first instance of the application with arguments from a second instance.
128+
/// </summary>
129+
/// <param name="args">List of arguments to supply the first instance of the application.</param>
130+
private static void ActivateFirstInstance()
134131
{
135-
return;
132+
// Set main window state and process command line args
133+
if (Application.Current == null)
134+
{
135+
return;
136+
}
137+
138+
((TApplication)Application.Current).OnSecondAppStarted();
136139
}
137140

138-
((TApplication)Application.Current).OnSecondAppStarted();
141+
#endregion
139142
}
140-
141-
#endregion
142143
}

0 commit comments

Comments
 (0)