A .NET library that ensures only one instance of your application is running at a time.
ktsu.SingleAppInstance is a lightweight .NET library that provides a robust mechanism to ensure only one instance of an application is running at a time. This is essential for desktop applications, services, or any software that requires instance exclusivity to prevent resource conflicts, maintain data integrity, or provide a consistent user experience.
- Single Instance Enforcement: Ensures only one instance of the application is running
- Enhanced Process Identification: Uses multiple attributes (PID, name, start time, executable path) for accurate identification
- Race Condition Handling: Manages potential conflicts when instances start simultaneously
- PID File Management: Stores process information securely in the application data directory
- Cross-Platform Support: Works on Windows, macOS, and Linux
- Backward Compatibility: Maintains compatibility with older versions that only stored the PID
- Simple API: Clean, easy-to-use interface with just two primary methods
Install-Package ktsu.SingleAppInstancedotnet add package ktsu.SingleAppInstance<PackageReference Include="ktsu.SingleAppInstance" Version="x.y.z" />The simplest way to use SingleAppInstance is to call the ExitIfAlreadyRunning method at the start of your application:
using ktsu.SingleAppInstance;
class Program
{
static void Main(string[] args)
{
SingleAppInstance.ExitIfAlreadyRunning();
// Your application code here
Console.WriteLine("Application is running.");
}
}If you prefer to explicitly handle the case where another instance is already running:
using ktsu.SingleAppInstance;
class Program
{
static void Main(string[] args)
{
if (SingleAppInstance.ShouldLaunch())
{
// Your application code here
Console.WriteLine("Application is running.");
}
else
{
// Handle the case where another instance is already running
Console.WriteLine("Another instance is already running.");
// Optional: Activate the existing window, pass command-line arguments, etc.
}
}
}using System.Windows;
using ktsu.SingleAppInstance;
namespace MyWpfApp
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (!SingleAppInstance.ShouldLaunch())
{
// Another instance is already running
MessageBox.Show("Application is already running.");
Shutdown();
return;
}
// Continue with normal startup
MainWindow = new MainWindow();
MainWindow.Show();
}
}
}For a more complex scenario where you want to pass commands to an existing instance:
using System;
using ktsu.SingleAppInstance;
class Program
{
static void Main(string[] args)
{
// Check if we can launch
if (!SingleAppInstance.ShouldLaunch())
{
// Another instance is already running
// Here you could implement an IPC mechanism to pass arguments to the running instance
Console.WriteLine("Another instance is already running. Sending arguments...");
// Example: Using named pipes, TCP, or memory-mapped files to communicate
// SendArgsToRunningInstance(args);
return;
}
// We're the primary instance
Console.WriteLine("Application is running.");
// Optional: Setup your IPC listening mechanism
// SetupIpcListener();
// Application main loop
Console.ReadLine();
}
}The static class that provides instance management functionality.
| Name | Return Type | Description |
|---|---|---|
ExitIfAlreadyRunning() |
void |
Exits the application with a status code of 0 if another instance is already running |
ShouldLaunch() |
bool |
Determines whether the application should launch based on whether another instance is running |
Under the hood, SingleAppInstance:
-
Stores a JSON-serialized
ProcessInfoobject containing:- Process ID
- Process name
- Start time
- Main module filename
-
Uses the application data directory to store the PID file. The file is named
.SingleAppInstance.pid. -
When checking for running instances, it:
- Reads the PID file
- Verifies if a process with the stored ID exists
- Confirms it's the same application by comparing process name and executable path
- Handles access restrictions and various edge cases
-
Implements a 1-second timeout in
ShouldLaunch()to detect race conditions when multiple instances start simultaneously.
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to update tests as appropriate and adhere to the existing coding style.
This project is licensed under the MIT License - see the LICENSE.md file for details.