forked from mikefourie-zz/MSBuildExplorer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
WpfSingleInstance.cs
112 lines (98 loc) · 5.01 KB
/
WpfSingleInstance.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//---------------------------------------------------------------------------------------------------------------------------
// <copyright file="WpfSingleInstance.cs">(c) Mike Fourie. All other rights reserved.</copyright>
//---------------------------------------------------------------------------------------------------------------------------
namespace MSBuildExplorer
{
using System;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
public static class WpfSingleInstance
{
internal static DispatcherTimer AutoExitAplicationIfStartupDeadlock;
internal enum SingleInstanceMode
{
/// <summary>
/// Do nothing.
/// </summary>
NotInited = 0,
/// <summary>
/// Every user can have own single instance.
/// </summary>
ForEveryUser,
}
public static void RemoveApplicationsStartupDeadlockForStartupCrushedWindows()
{
Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
AutoExitAplicationIfStartupDeadlock = new DispatcherTimer(
TimeSpan.FromSeconds(6),
DispatcherPriority.ApplicationIdle,
(o, args) =>
{
if (Application.Current.Windows.Cast<Window>().Count(window => !double.IsNaN(window.Left)) == 0)
{
// For that exit no interceptions.
Environment.Exit(0);
}
},
Application.Current.Dispatcher);
}),
DispatcherPriority.ApplicationIdle);
}
/// <summary>
/// Processing single instance in <see cref="SingleInstanceMode"/> <see cref="SingleInstanceMode.ForEveryUser"/> mode.
/// </summary>
internal static void Make()
{
Make(SingleInstanceMode.ForEveryUser);
}
internal static void Make(SingleInstanceMode singleInstanceModes)
{
var appName = Application.Current.GetType().Assembly.ManifestModule.ScopeName;
var windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
var keyUserName = windowsIdentity != null ? windowsIdentity.User.ToString() : string.Empty;
// Be careful! Max 260 chars!
var eventWaitHandleName = string.Format("{0}{1}", appName, singleInstanceModes == SingleInstanceMode.ForEveryUser ? keyUserName : string.Empty);
try
{
using (var eventWaitHandle = EventWaitHandle.OpenExisting(eventWaitHandleName))
{
// It informs first instance about other startup attempting.
eventWaitHandle.Set();
}
Environment.Exit(0);
}
catch
{
// It's first instance.
// Register EventWaitHandle.
using (var eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventWaitHandleName))
{
ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, OtherInstanceAttemptedToStart, null, Timeout.Infinite, false);
}
RemoveApplicationsStartupDeadlockForStartupCrushedWindows();
}
}
private static void OtherInstanceAttemptedToStart(object state, bool timedOut)
{
RemoveApplicationsStartupDeadlockForStartupCrushedWindows();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
Application.Current.MainWindow.Activate();
Application.Current.MainWindow.Topmost = true;
Application.Current.MainWindow.Topmost = false;
Application.Current.MainWindow.Focus();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}));
}
}
}