ktsu.SingleAppInstance
1.2.5
Prefix Reserved
See the version list below for details.
dotnet add package ktsu.SingleAppInstance --version 1.2.5
NuGet\Install-Package ktsu.SingleAppInstance -Version 1.2.5
<PackageReference Include="ktsu.SingleAppInstance" Version="1.2.5" />
<PackageVersion Include="ktsu.SingleAppInstance" Version="1.2.5" />
<PackageReference Include="ktsu.SingleAppInstance" />
paket add ktsu.SingleAppInstance --version 1.2.5
#r "nuget: ktsu.SingleAppInstance, 1.2.5"
#addin nuget:?package=ktsu.SingleAppInstance&version=1.2.5
#tool nuget:?package=ktsu.SingleAppInstance&version=1.2.5
ktsu.SingleAppInstance
A .NET library that ensures only one instance of your application is running at a time.
Introduction
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.
Features
- 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
Installation
Package Manager Console
Install-Package ktsu.SingleAppInstance
.NET CLI
dotnet add package ktsu.SingleAppInstance
Package Reference
<PackageReference Include="ktsu.SingleAppInstance" Version="x.y.z" />
Usage Examples
Basic Example
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.");
}
}
Custom Launch Logic
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.
}
}
}
Advanced Usage
WPF Application Integration
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();
}
}
}
Console Application with Command Passing
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();
}
}
API Reference
SingleAppInstance
Class
The static class that provides instance management functionality.
Methods
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 |
Technical Implementation
Under the hood, SingleAppInstance:
Stores a JSON-serialized
ProcessInfo
object 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.
Contributing
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.
License
This project is licensed under the MIT License - see the LICENSE.md file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- ktsu.AppDataStorage (>= 1.15.0)
-
net9.0
- ktsu.AppDataStorage (>= 1.15.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.2.6-pre.18 | 116 | 5/20/2025 |
1.2.6-pre.15 | 72 | 5/17/2025 |
1.2.6-pre.14 | 127 | 5/16/2025 |
1.2.6-pre.13 | 196 | 5/15/2025 |
1.2.6-pre.12 | 194 | 5/14/2025 |
1.2.6-pre.11 | 194 | 5/13/2025 |
1.2.6-pre.10 | 227 | 5/12/2025 |
1.2.6-pre.9 | 164 | 5/11/2025 |
1.2.6-pre.8 | 104 | 5/10/2025 |
1.2.6-pre.7 | 46 | 5/9/2025 |
1.2.6-pre.6 | 117 | 5/8/2025 |
1.2.6-pre.5 | 117 | 5/7/2025 |
1.2.6-pre.4 | 114 | 5/6/2025 |
1.2.6-pre.3 | 114 | 5/5/2025 |
1.2.6-pre.2 | 116 | 5/4/2025 |
1.2.6-pre.1 | 111 | 5/4/2025 |
1.2.5 | 145 | 5/4/2025 |
1.2.5-pre.3 | 107 | 4/29/2025 |
1.2.5-pre.2 | 128 | 4/28/2025 |
1.2.5-pre.1 | 61 | 4/26/2025 |
1.2.4 | 141 | 4/25/2025 |
1.2.3 | 111 | 4/19/2025 |
1.2.2 | 176 | 4/18/2025 |
1.2.2-pre.3 | 60 | 4/4/2025 |
1.2.2-pre.2 | 113 | 4/4/2025 |
1.2.2-pre.1 | 132 | 3/31/2025 |
1.2.1 | 147 | 3/30/2025 |
1.2.0 | 149 | 3/30/2025 |
1.1.1-pre.2 | 74 | 3/29/2025 |
1.1.1-pre.1 | 462 | 3/25/2025 |
1.1.0 | 119 | 2/17/2025 |
1.0.0-pre.19 | 71 | 2/14/2025 |
1.0.0-pre.18 | 72 | 2/6/2025 |
1.0.0-pre.17 | 68 | 2/5/2025 |
1.0.0-pre.16 | 61 | 2/5/2025 |
1.0.0-pre.15 | 69 | 2/3/2025 |
1.0.0-pre.14 | 70 | 2/3/2025 |
1.0.0-pre.13 | 62 | 2/3/2025 |
1.0.0-pre.12 | 78 | 2/2/2025 |
1.0.0-pre.11 | 65 | 1/31/2025 |
1.0.0-pre.10 | 63 | 1/30/2025 |
1.0.0-pre.9 | 75 | 1/28/2025 |
1.0.0-pre.8 | 64 | 1/26/2025 |
1.0.0-pre.7 | 58 | 1/24/2025 |
1.0.0-pre.6 | 65 | 1/22/2025 |
1.0.0-pre.5 | 65 | 1/20/2025 |
1.0.0-pre.4 | 57 | 1/18/2025 |
1.0.0-pre.3 | 58 | 1/16/2025 |
1.0.0-pre.2 | 43 | 1/14/2025 |
1.0.0-pre.1 | 65 | 1/13/2025 |
0.0.1-pre.1 | 58 | 1/13/2025 |
## v1.2.5 (patch)
Changes since v1.2.4:
- Remove .markdownlint.json configuration file, update DESCRIPTION.md for clarity, and change project SDK references in .csproj files to ktsu.Sdk.Lib and ktsu.Sdk.Test version 1.8.0. ([@matt-edmondson](https://github.com/matt-edmondson))
- Remove Directory.Build.props, Directory.Build.targets, and several PowerShell scripts for metadata and version management. Update SingleAppInstance and its tests to use 'var' for variable declarations and add copyright information. ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.2.5-pre.3 (prerelease)
Changes since v1.2.5-pre.2:
- Bump ktsu.AppDataStorage from 1.11.0 to 1.15.0 in the ktsu group ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.2.5-pre.2 (prerelease)
Changes since v1.2.5-pre.1:
- Bump ktsu.AppDataStorage from 1.7.2 to 1.11.0 in the ktsu group ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.2.5-pre.1 (prerelease)
Changes since v1.2.4:
- Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.2.4 (patch)
Changes since v1.2.3:
- Update README to match standard template format ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.2.3 (patch)
Changes since v1.2.2:
- Add tests for SingleAppInstance behavior with no other instance running and custom launch logic ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance SingleAppInstance to store and verify process information in JSON format ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance memory.jsonl to include advanced process detection and compatibility details for SingleAppInstance class ([@matt-edmondson](https://github.com/matt-edmondson))
- Refine README.md for clarity and usage instructions of SingleAppInstance ([@matt-edmondson](https://github.com/matt-edmondson))
- Update language-specific guidelines to clarify test execution commands and improve resource management ([@matt-edmondson](https://github.com/matt-edmondson))
- Refine README.md to enhance feature descriptions and clarify technical implementation details for SingleAppInstance ([@matt-edmondson](https://github.com/matt-edmondson))
- Set max cpus for tests to 1 ([@matt-edmondson](https://github.com/matt-edmondson))
- Add memory.jsonl file with project and class details ([@matt-edmondson](https://github.com/matt-edmondson))
- Update test command to run in a single process ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance memory.jsonl to include additional details for SingleAppInstance tests and project structure ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor SingleAppInstanceTests to simplify file deletion logic and remove unnecessary try-finally blocks, ensuring clearer test flow and improved readability. ([@matt-edmondson](https://github.com/matt-edmondson))
- Update Copilot instructions for .NET project build and testing guidelines ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor SingleAppInstanceTests for better isolation ([@matt-edmondson](https://github.com/matt-edmondson))
- Organize and enhance Copilot documentation with detailed guidelines on memory usage, coding standards, and project management practices. ([@matt-edmondson](https://github.com/matt-edmondson))
- Refine workflow guidelines for clarity on specialized tool usage and documentation checks ([@matt-edmondson](https://github.com/matt-edmondson))
- Add SingleAppInstance.Test project to solution and configure build settings ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor SingleAppInstanceTests to improve clarity and structure of test methods, ensuring accurate PID file handling and process information validation. ([@matt-edmondson](https://github.com/matt-edmondson))
- Update language-specific guidelines to clarify tool usage and fallback options ([@matt-edmondson](https://github.com/matt-edmondson))
- Add workflow and process guidelines to Copilot instructions ([@matt-edmondson](https://github.com/matt-edmondson))
- Comment out MaxCpuCount setting in .runsettings to disable process-level parallelization ([@matt-edmondson](https://github.com/matt-edmondson))
- Clarify command line usage by providing an example for non-interactive mode with `git` commands ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance SingleAppInstanceTests by adding assertions to verify PID file handling and initial state checks ([@matt-edmondson](https://github.com/matt-edmondson))
- Add guidelines for using command line in non-interactive mode and directory context ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.2.2 (patch)
Changes since v1.2.1:
- Add comprehensive Copilot instructions and memory management guidelines ([@matt-edmondson](https://github.com/matt-edmondson))
- Add markdownlint configuration file for linting rules ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.2.2-pre.3 (prerelease)
Changes since v1.2.2-pre.2:
- Bump ktsu.AppDataStorage from 1.7.1 to 1.7.2 in the ktsu group ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.2.2-pre.2 (prerelease)
Changes since v1.2.2-pre.1:
- Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.2.2-pre.1 (prerelease)
Incremental prerelease update.
## v1.2.1 (patch)
Changes since v1.2.0:
- Update packages ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.2.0 (minor)
Changes since v1.1.0:
- Add LICENSE template ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.1.1-pre.2 (prerelease)
Changes since v1.1.1-pre.1:
- Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.1.1-pre.1 (prerelease)
Changes since v1.1.0:
- Sync .editorconfig ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync .gitignore ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync Directory.Build.targets ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.1.0 (minor)
Changes since v1.0.0-pre.19:
- Apply new editorconfig ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.0.0-pre.19 (prerelease)
Changes since v1.0.0-pre.18:
- Bump ktsu.AppDataStorage from 1.4.7 to 1.5.0 in the ktsu group ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.0.0-pre.18 (prerelease)
Changes since v1.0.0-pre.17:
- Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.0.0-pre.17 (prerelease)
Changes since v1.0.0-pre.16:
- Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.0.0-pre.16 (prerelease)
Changes since v1.0.0-pre.15:
- Sync scripts\make-changelog.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
- Sync scripts\make-version.ps1 ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.0.0-pre.15 (prerelease)
Changes since v1.0.0-pre.14:
- Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.0.0-pre.14 (prerelease)
Changes since v1.0.0-pre.13:
- Review Feedback ([@Damon3000s](https://github.com/Damon3000s))
- Revert unintended changes ([@Damon3000s](https://github.com/Damon3000s))
- Create the directory the Pid will be stored in ([@Damon3000s](https://github.com/Damon3000s))
## v1.0.0-pre.13 (prerelease)
Changes since v1.0.0-pre.12:
- Sync .github\workflows\dotnet.yml ([@ktsu[bot]](https://github.com/ktsu[bot]))
## v1.0.0-pre.12 (prerelease)
Changes since v1.0.0-pre.11:
## v1.0.0-pre.11 (prerelease)
Changes since v1.0.0-pre.10:
## v1.0.0-pre.10 (prerelease)
Changes since v1.0.0-pre.9:
- Catch DirectoryNotFoundException ([@Damon3000s](https://github.com/Damon3000s))
## v1.0.0-pre.9 (prerelease)
Changes since v1.0.0-pre.8:
- Bump MSTest from 3.7.2 to 3.7.3 ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.0.0-pre.8 (prerelease)
Changes since v1.0.0-pre.7:
## v1.0.0-pre.7 (prerelease)
Changes since v1.0.0-pre.6:
## v1.0.0-pre.6 (prerelease)
Changes since v1.0.0-pre.5:
- Bump MSTest from 3.7.1 to 3.7.2 ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.0.0-pre.5 (prerelease)
Changes since v1.0.0-pre.4:
- Bump coverlet.collector from 6.0.3 to 6.0.4 ([@dependabot[bot]](https://github.com/dependabot[bot]))
## v1.0.0-pre.4 (prerelease)
Changes since v1.0.0-pre.3:
## v1.0.0-pre.3 (prerelease)
Changes since v1.0.0-pre.2:
## v1.0.0-pre.2 (prerelease)
Changes since v1.0.0-pre.1:
- Remove ktsu.ScopedAction package from project ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.0.0-pre.1 (prerelease)
Incremental prerelease update.
## v0.0.1-pre.1 (prerelease)
Incremental prerelease update.