diff --git a/Program.cs b/Program.cs index 39106f9..68efc17 100644 --- a/Program.cs +++ b/Program.cs @@ -42,7 +42,6 @@ private enum ExecutionState : uint public PreventLockApp() { - // Safe version initialization with null checks var version = Assembly.GetExecutingAssembly().GetName().Version ?? new Version(1, 0, 0); appVersion = $"v{version.Major}.{version.Minor}.{version.Build}"; versionFont = new Font("Segoe UI", 8.25f, FontStyle.Italic); @@ -56,7 +55,6 @@ public PreventLockApp() settings = LoadSettings(); isRunning = true; - // Validate and fix startup path if needed (NEW) ValidateAndFixStartupPath(); trayIcon = new NotifyIcon() @@ -70,7 +68,6 @@ public PreventLockApp() new Thread(WorkerThreadMethod) { IsBackground = true }.Start(); } - // NEW METHOD: Fixes startup path if executable was moved private void ValidateAndFixStartupPath() { try @@ -92,7 +89,6 @@ private void ValidateAndFixStartupPath() catch { /* Silent failure is acceptable */ } } - /* ALL OTHER METHODS REMAIN EXACTLY THE SAME AS YOUR ORIGINAL CODE */ private AppSettings LoadSettings() { try @@ -379,16 +375,174 @@ protected override void Dispose(bool disposing) static class Program { + private static Mutex? _mutex; + private const string AppName = "Spotify Prevent Lock"; + [STAThread] static void Main() { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - // Wait for system tray to initialize - Thread.Sleep(3000); - - Application.Run(new PreventLockApp()); + const string mutexName = "Global\\SpotifyPreventLock"; + bool createdNew; + _mutex = new Mutex(true, mutexName, out createdNew); + + if (!createdNew) + { + ShowRunningInstanceWarning(); + return; + } + + try + { + var versionCheck = CheckRunningVersions(); + if (versionCheck != VersionCheckResult.Continue) + { + if (versionCheck == VersionCheckResult.Restart) + { + Thread.Sleep(500); // Brief pause before restart + Process.Start(new ProcessStartInfo + { + FileName = Application.ExecutablePath, + UseShellExecute = true + }); + } + return; + } + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new PreventLockApp()); + } + finally + { + _mutex?.ReleaseMutex(); + _mutex?.Dispose(); + } + } + + private enum VersionCheckResult + { + Continue, + Exit, + Restart + } + + private static void ShowRunningInstanceWarning() + { + MessageBox.Show( + $"{AppName} is already running.\n\n" + + "If updating version or exe file location.\n" + + "Please exit old instance and rerun new version to update.", + "Application Running", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + } + + private static VersionCheckResult CheckRunningVersions() + { + var currentProcess = Process.GetCurrentProcess(); + var currentVersion = GetCurrentVersion(); + + foreach (var process in Process.GetProcessesByName(currentProcess.ProcessName)) + { + try + { + if (process.Id == currentProcess.Id) continue; + + var runningVersion = GetProcessVersion(process); + if (runningVersion == null) continue; + + int comparison = runningVersion.CompareTo(currentVersion); + + if (comparison > 0) // Newer version running + { + MessageBox.Show( + $"A newer version (v{runningVersion}) is already running!\n\n" + + $"Please close this version (v{currentVersion}) and use the newer one.", + "New Version Detected", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + return VersionCheckResult.Exit; + } + else if (comparison < 0) // Older version running + { + return HandleOlderVersion(process, currentVersion, runningVersion); + } + else // Same version running + { + return VersionCheckResult.Exit; + } + } + catch { /* Ignore inaccessible processes */ } + } + return VersionCheckResult.Continue; + } + + private static Version GetCurrentVersion() + { + return Assembly.GetExecutingAssembly().GetName().Version ?? new Version(1, 0, 0); + } + + private static Version? GetProcessVersion(Process process) + { + try + { + string? path = process.MainModule?.FileName; + if (string.IsNullOrEmpty(path)) return null; + + var versionInfo = FileVersionInfo.GetVersionInfo(path); + return string.IsNullOrEmpty(versionInfo.FileVersion) + ? null + : new Version(versionInfo.FileVersion); + } + catch + { + return null; + } + } + + private static VersionCheckResult HandleOlderVersion(Process process, Version currentVersion, Version runningVersion) + { + var result = MessageBox.Show( + $"An older version (v{runningVersion}) is running.\n\n" + + $"Current version: v{currentVersion}\n\n" + + "Would you like to upgrade now?", + "Upgrade Available", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + if (result != DialogResult.Yes) return VersionCheckResult.Exit; + + try + { + // Try graceful shutdown first + if (!process.CloseMainWindow()) + { + process.Kill(); + } + + if (!process.WaitForExit(3000)) + { + MessageBox.Show( + "Could not close the previous version.\n" + + "Please close it manually and run the new version again.", + "Upgrade Warning", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + return VersionCheckResult.Exit; + } + + return VersionCheckResult.Restart; + } + catch (Exception ex) + { + MessageBox.Show( + $"Upgrade failed: {ex.Message}\n\n" + + "Please close the old version manually and try again.", + "Upgrade Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return VersionCheckResult.Exit; + } } } } diff --git a/SpotifyPreventLock.csproj b/SpotifyPreventLock.csproj index 85040b9..ba9458c 100644 --- a/SpotifyPreventLock.csproj +++ b/SpotifyPreventLock.csproj @@ -8,7 +8,7 @@ true - 1.1.0 + 1.1.1 dev