-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
128 lines (111 loc) · 4.58 KB
/
Copy pathProgram.cs
File metadata and controls
128 lines (111 loc) · 4.58 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
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using PBIPortWrapper.Services;
namespace PBIPortWrapper
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// #64: concurrent wrappers share config.json/log.txt without
// coordination and compete for the same fixed ports - allow only one
// instance and front the existing one instead. The mutex handle is
// held for the process lifetime; the kernel object disappears with
// the process, so a crashed wrapper never blocks the next start.
using var singleInstance = AcquireSingleInstanceMutex(out bool isFirstInstance);
if (!isFirstInstance)
{
FrontExistingInstance();
return;
}
// #87: --silent makes the app start hidden in the tray (used by the
// auto-start registry key so the wrapper doesn't pop a window at login).
bool startSilent = args.Any(a => a.Equals("--silent", StringComparison.OrdinalIgnoreCase));
// Set up global exception handlers
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += Application_ThreadException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
ApplicationConfiguration.Initialize();
Application.Run(new MainForm(startSilent));
}
private static Mutex AcquireSingleInstanceMutex(out bool isFirstInstance)
{
try
{
return new Mutex(initiallyOwned: true, @"Global\PBIPortWrapper_SingleInstance", out isFirstInstance);
}
catch (UnauthorizedAccessException)
{
// The mutex exists but belongs to another session/user - still a
// running wrapper (ports are machine-wide, so this counts too).
isFirstInstance = false;
return null;
}
}
private static void FrontExistingInstance()
{
var current = Process.GetCurrentProcess();
foreach (var process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id == current.Id) continue;
var hwnd = process.MainWindowHandle;
if (hwnd != IntPtr.Zero)
{
if (IsIconic(hwnd)) ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return;
}
}
// No window to front (minimized to tray, or the other instance runs
// in another session) - at least say why nothing opened.
MessageBox.Show(
"PBI Port Wrapper is already running - check the system tray.",
"PBI Port Wrapper", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private const int SW_RESTORE = 9;
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is Exception ex)
{
HandleException(ex);
}
}
private static void HandleException(Exception ex)
{
string errorMessage = $"An unexpected error occurred:\n\n{ex.Message}\n\nStack Trace:\n{ex.StackTrace}";
MessageBox.Show(
errorMessage,
"PBI Port Wrapper - Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
// Log using LoggerService
try
{
var logger = new LoggerService();
logger.LogError("Global", "Unhandled exception occurred", ex);
}
catch
{
// If we can't log, just ignore
}
}
}
}