-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
142 lines (123 loc) · 4.74 KB
/
Copy pathProgram.cs
File metadata and controls
142 lines (123 loc) · 4.74 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System.Diagnostics;
internal static class Program
{
private static Mutex? _instanceMutex;
[STAThread]
static void Main(string[] args)
{
if (!ClosePreviousInstanceFromSamePath()) return;
AppLog.Initialize();
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += (s, e) =>
{
Debug.WriteLine(e.Exception);
AppLog.Error("Unhandled WinForms exception.", e.Exception);
};
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
{
if (e.ExceptionObject is Exception ex)
{
Debug.WriteLine(ex);
AppLog.Error("Unhandled application exception.", ex);
}
};
_instanceMutex = new Mutex(
true,
@"Local\TeamsIOBoard_SingleInstance",
out bool createdNew
);
if (!createdNew)
{
// A previous process can briefly retain the mutex while Windows is
// finishing its shutdown. Avoid starting two message loops.
return;
}
var defaultProxy = System.Net.WebRequest.DefaultWebProxy;
if (defaultProxy is not null)
{
defaultProxy.Credentials =
System.Net.CredentialCache.DefaultNetworkCredentials;
System.Net.Http.HttpClient.DefaultProxy = defaultProxy;
}
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var config = AppConfig.Load();
if (config.Validate() is not null)
{
using var setup = new ConnectionSettingsForm(config);
if (setup.ShowDialog() != DialogResult.OK) return;
config = AppConfig.Load();
}
// The setup dialog may install a WinForms synchronization context.
// Authenticate on the thread pool so blocking here cannot deadlock
// continuations waiting for that now-closed modal message loop.
// The board and clipboard still run on this original STA thread.
var service = Task.Run(() => TeamsIoService.CreateAsync(config))
.GetAwaiter()
.GetResult();
var form = new BoardForm(service, config);
BoardHelpers.Theme.ApplyTitleBarTheme(form);
Application.Run(form);
}
catch (Exception ex)
{
AppLog.Error("Application startup failed.", ex);
var changeSettings = MessageBox.Show(
"TeamsIO could not start.\n\n" + ex.Message + "\n\nOpen connection settings?",
"TeamsIO Startup Failure", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
if (changeSettings == DialogResult.Yes)
{
using var settings = new ConnectionSettingsForm(AppConfig.Load());
if (settings.ShowDialog() == DialogResult.OK) Application.Restart();
}
}
}
private static bool ClosePreviousInstanceFromSamePath()
{
using var current = Process.GetCurrentProcess();
var currentPath = Environment.ProcessPath;
if (string.IsNullOrWhiteSpace(currentPath))
return true;
foreach (var process in Process.GetProcessesByName(current.ProcessName))
{
using (process)
{
if (process.Id == current.Id || !IsSameExecutable(process, currentPath))
continue;
try
{
if (process.MainWindowHandle != IntPtr.Zero)
process.CloseMainWindow();
if (!process.WaitForExit(2000))
{
MessageBox.Show("TeamsIO is still closing. Please try again in a moment.", "TeamsIO");
return false;
}
}
catch (InvalidOperationException)
{
// The previous process exited between discovery and shutdown.
}
catch (System.ComponentModel.Win32Exception ex)
{
AppLog.Error("Could not close the previous TeamsIO process.", ex);
}
}
}
return true;
}
private static bool IsSameExecutable(Process process, string currentPath)
{
try
{
return string.Equals(
process.MainModule?.FileName,
currentPath,
StringComparison.OrdinalIgnoreCase);
}
catch (System.ComponentModel.Win32Exception) { return false; }
catch (InvalidOperationException) { return false; }
}
}