Skip to content

Commit

Permalink
Add multi-instance detection to YAMDCC config editor
Browse files Browse the repository at this point in the history
If the config editor is already running, this will cause the existing instance to be focused. Note that this multi-instance detection system won't work with previous commits/versions of the YAMDCC config editor.
  • Loading branch information
Sparronator9999 committed Jan 7, 2025
1 parent 40a3d74 commit 18c695a
Showing 1 changed file with 109 additions and 69 deletions.
178 changes: 109 additions & 69 deletions YAMDCC.ConfigEditor/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
// YAMDCC. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
using System.Windows.Forms;
using YAMDCC.Common;
using YAMDCC.Common.Dialogs;
Expand All @@ -26,6 +29,8 @@ namespace YAMDCC.ConfigEditor
{
internal static class Program
{
private const int SW_RESTORE = 9;

/// <summary>
/// The main entry point for the application.
/// </summary>
Expand Down Expand Up @@ -55,101 +60,130 @@ private static void Main()
return;
}

// Make sure the application data directory structure is set up
// because apparently windows services don't know how to create
// directories:
Directory.CreateDirectory(Paths.Logs);

if (!Utils.ServiceExists("yamdccsvc"))
// multi-instance detection
// NOTE: GUID is used to prevent conflicts with potential
// identically named but different program
// based on: https://stackoverflow.com/a/184143
using (Mutex mutex = new(true, "{10572c4f-894e-4837-b31c-356d70c44e19}", out bool createdNew))
{
if (File.Exists("yamdccsvc.exe"))
// this instance is the first to open; proceed as normal:
if (createdNew)
{
if (MessageBox.Show(
Strings.GetString("dlgSvcNotInstalled"),
"Service not installed",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.Yes)
// Make sure the application data directory structure is set up
// because apparently windows services don't know how to create
// directories:
Directory.CreateDirectory(Paths.Logs);

if (!Utils.ServiceExists("yamdccsvc"))
{
ProgressDialog dlg = new(Strings.GetString("dlgSvcInstalling"), (e) =>
if (File.Exists("yamdccsvc.exe"))
{
e.Result = false;
if (Utils.InstallService("yamdccsvc"))
if (MessageBox.Show(
Strings.GetString("dlgSvcNotInstalled"),
"Service not installed",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.Yes)
{
if (Utils.StartService("yamdccsvc"))
ProgressDialog dlg = new(Strings.GetString("dlgSvcInstalling"), (e) =>
{
e.Result = true;
}
else
e.Result = false;
if (Utils.InstallService("yamdccsvc"))
{
if (Utils.StartService("yamdccsvc"))
{
e.Result = true;
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcStartCrash"));
}
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcInstallFail"));
}
});
dlg.ShowDialog();

if (dlg.Result is bool b && b)
{
Utils.ShowError(Strings.GetString("dlgSvcStartCrash"));
// Start the program when the service finishes starting:
Start();
}
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcInstallFail"));
}
});
dlg.ShowDialog();

if (dlg.Result is bool b && b)
return;
}
else
{
// Start the program when the service finishes starting:
Start();
Utils.ShowError(Strings.GetString("dlgSvcNotFound"));
return;
}
}
return;
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcNotFound"));
return;
}
}

// Check if the service is stopped:
ServiceController yamdccSvc = new("yamdccsvc");
try
{
ServiceControllerStatus status = yamdccSvc.Status;
if (status == ServiceControllerStatus.Stopped)
{
if (MessageBox.Show(
Strings.GetString("dlgSvcStopped"),
"Service not running", MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.Yes)
// Check if the service is stopped:
ServiceController yamdccSvc = new("yamdccsvc");
try
{
ProgressDialog dlg = new(Strings.GetString("dlgSvcStarting"), (e) =>
ServiceControllerStatus status = yamdccSvc.Status;
if (status == ServiceControllerStatus.Stopped)
{
if (Utils.StartService("yamdccsvc"))
if (MessageBox.Show(
Strings.GetString("dlgSvcStopped"),
"Service not running", MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.Yes)
{
e.Result = false;
ProgressDialog dlg = new(Strings.GetString("dlgSvcStarting"), (e) =>
{
if (Utils.StartService("yamdccsvc"))
{
e.Result = false;
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcStartCrash"));
e.Result = true;
}
});
dlg.ShowDialog();

if (dlg.Result is bool b && b)
{
return;
}
}
else
{
Utils.ShowError(Strings.GetString("dlgSvcStartCrash"));
e.Result = true;
return;
}
});
dlg.ShowDialog();

if (dlg.Result is bool b && b)
{
return;
}
}
else
finally
{
return;
yamdccSvc?.Close();
}

// Start the program when the service finishes starting:
Start();
}
else
{
// YAMDCC is already running, focus
// (and restore, if minimised) its window:
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
if (process.MainWindowHandle != IntPtr.Zero)
{
ShowWindow(process.MainWindowHandle, SW_RESTORE);
SetForegroundWindow(process.MainWindowHandle);
}
break;
}
}
}
}
finally
{
yamdccSvc?.Close();
}

// Start the program when the service finishes starting:
Start();
}

private static void Start()
Expand Down Expand Up @@ -187,5 +221,11 @@ private static void Start()

Application.Run(new MainWindow());
}

[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
}

0 comments on commit 18c695a

Please sign in to comment.