How to Run Only One Instance of Application

How to Run Only One Instance of Application

You may used named mutex.

Code sample from the article:

WINAPI WinMain(
HINSTANCE, HINSTANCE, LPSTR, int)
{
try {
// Try to open the mutex.
HANDLE hMutex = OpenMutex(
MUTEX_ALL_ACCESS, 0, "MyApp1.0");

if (!hMutex)
// Mutex doesn’t exist. This is
// the first instance so create
// the mutex.
hMutex =
CreateMutex(0, 0, "MyApp1.0");
else
// The mutex exists so this is the
// the second instance so return.
return 0;

Application->Initialize();
Application->CreateForm(
__classid(TForm1), &Form1);
Application->Run();

// The app is closing so release
// the mutex.
ReleaseMutex(hMutex);
}
catch (Exception &exception) {
Application->
ShowException(&exception);
}
return 0;
}

How to create a single instance application in C or C++

A good way is:

#include <sys/file.h>
#include <errno.h>

int pid_file = open("/var/run/whatever.pid", O_CREAT | O_RDWR, 0666);
int rc = flock(pid_file, LOCK_EX | LOCK_NB);
if(rc) {
if(EWOULDBLOCK == errno)
; // another instance is running
}
else {
// this is the first instance
}

Note that locking allows you to ignore stale pid files (i.e. you don't have to delete them). When the application terminates for any reason the OS releases the file lock for you.

Pid files are not terribly useful because they can be stale (the file exists but the process does not). Hence, the application executable itself can be locked instead of creating and locking a pid file.

A more advanced method is to create and bind a unix domain socket using a predefined socket name. Bind succeeds for the first instance of your application. Again, the OS unbinds the socket when the application terminates for any reason. When bind() fails another instance of the application can connect() and use this socket to pass its command line arguments to the first instance.

Allow only one application instance

Use the “Make single instance application” flag; in the solution explorer, right-click the project and select properties. See this question for more details.

MSDN documentation here.

Screenshot:

Sample Image

Run the current application as Single Instance and show the previous instance

I propose you a different method, using a combination of the System.Threading.Mutex class and UIAutomation AutomationElement class.

A Mutex can be, as you already know, a simple string. You can assign an application a Mutex in the form of a GUID, but it can be anything else.

Let's assume this is the current Application Mutex:

string ApplicationMutex = "BcFFcd23-3456-6543-Fc44abcd1234";
//Or
string ApplicationMutex = "Global\BcFFcd23-3456-6543-Fc44abcd1234";

Note:

Use the "Global\" Prefix to define the scope of the Mutex. If no prefix is specified, the "Local\" prefix is assumed and used instead. This will prevent a single instance of the process when multiple desktops are active or Terminal Services is running on the server.

If we want to verify whether another running Process has already registered the same Mutex, we try to register our Mutex and if it fails, another instance of our Application is already running.

We let the user know that the Application supports only a single instance, then switch to the running process, showing its interface and finally exit the duplicate Application, disposing of the Mutex.

The method to activate a previous instance of the Application may vary based on the type of the Application, but only some details change.

We can use Process..GetProcesses() to retrieve a list of the running processes and verify if one of them has the same details as ours.

Here, you have a windowed Application (it has an UI), so it's already possible to filter the list, excluding those processes that do not have a MainWindowHandle.

Process[] windowedProcesses = 
Process.GetProcesses().Where(p => p.MainWindowHandle != IntPtr.Zero).ToArray();

To identify the right one, we could test if the Process.ProcessName is the same.

But this name is tied to the executable name. If the file name changes (someone changes it for some reason), we will never identify the Process this way.

One possible way to identify the right Process is to test the Process.MainModule.FileVersionInfo.ProductName and check whether it's the same.

When found, it's possible to bring the original Application to front with an AutomationElement created using the MainWindowHandle of the identified Process.

The AutomationElement can automate different Patterns (sort of controls that provide automation functionalities for UI elements).

A WindowPattern allows to control a window-base control (the Platform is irrelevant, could be a WinForms' Form or a WPF's Window).

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
WindowPattern wPattern = element.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
wPattern.SetWindowVisualState(WindowVisualState.Normal);

To use the UIAutomation functionalities, you have to add these refereneces in your Project:

- UIAutomationClient
- UIAutomationTypes

UPDATE:
Since the Application's Form might be hidden, Process.GetProcesses() will not find it's Window handle, thus AutomationElement.FromHandle() cannot be used to identify the Form Window.

A possible workaround, without dismissing the UIAutomation "pattern", is to register an Automation event, using Automation.AddAutomationEventHandler, which allows to receive a notification when an UI Automation events occurs, such as a new Window is about to be shown (a Program is run).

The event is registerd only if the Application needs to run as Single Instance. When the event is raised, the new Process AutomationElement Name (the Windows Title Text) is compared to the current and, if it's the same, the hidden Form will un-hide and show itself in Normal state.

As a fail-safe measure, we present an information MessageBox. The MessageBox caption has the same caption as the Application MainForm.

(Tested with a Form with its WindowsState set to Minimized and its Visible property set to false).


After the orginal Process has been brought to front, we just neeed to close the current thread and release the resources we created (mainly the Mutex, in this case).

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Automation;
using System.Windows.Forms;

static class Program
{
static Mutex mutex = null;

[STAThread]
static void Main()
{
Application.ThreadExit += ThreadOnExit;
string applicationMutex = @"Global\BcFFcd23-3456-6543-Fc44abcd1234";
mutex = new Mutex(true, applicationMutex);
bool singleInstance = mutex.WaitOne(0, false);
if (!singleInstance)
{
string appProductName = Process.GetCurrentProcess().MainModule.FileVersionInfo.ProductName;
Process[] windowedProcesses =
Process.GetProcesses().Where(p => p.MainWindowHandle != IntPtr.Zero).ToArray();

foreach (Process process in windowedProcesses.Where(p => p.MainModule.FileVersionInfo.ProductName == appProductName))
{
if (process.Id != Process.GetCurrentProcess().Id)
{
AutomationElement wElement = AutomationElement.FromHandle(process.MainWindowHandle);
if (wElement.Current.IsOffscreen)
{
WindowPattern wPattern = wElement.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
#if DEBUG
WindowInteractionState state = wPattern.Current.WindowInteractionState;
Debug.Assert(!(state == WindowInteractionState.NotResponding), "The application is not responding");
Debug.Assert(!(state == WindowInteractionState.BlockedByModalWindow), "Main Window blocked by a Modal Window");
#endif
wPattern.SetWindowVisualState(WindowVisualState.Normal);
break;
}
}
}
Thread.Sleep(200);
MessageBox.Show("Application already running", "MyApplicationName",
MessageBoxButtons.OK, MessageBoxIcon.Information,
MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification);
}

if (SingleInstance) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyAppMainForm());
}
else {
Application.ExitThread();
}
}
private static void ThreadOnExit(object s, EventArgs e)
{
mutex.Dispose();
Application.ThreadExit -= ThreadOnExit;
Application.Exit();
}
}

In the Application MainForm constructor:

(this is used in case the Application's Main Window is hidden when a new instance is run, hence the procedure in Program.cs cannot find its handle)

public partial class MyAppMainForm : Form
{
public MyAppMainForm()
{
InitializeComponent();
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement,
TreeScope.Subtree, (uiElm, evt) =>
{
AutomationElement element = uiElm as AutomationElement;
string windowText = element.Current.Name;
if (element.Current.ProcessId != Process.GetCurrentProcess().Id && windowText == this.Text)
{
this.BeginInvoke(new MethodInvoker(() =>
{
this.WindowState = FormWindowState.Normal;
this.Show();
}));
}
});
}
}

How to ensure only a single instance of my application runs?

I use JCL to do this:

program MyProgram;

uses
JclAppInst;

begin
JclAppInstances.CheckSingleInstance; // Added instance checking
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

Documentation for this, and the notification scheme, is at the JCL Wiki.

How to let run only one instance of application at a time?

You could try JUnique. It's an open source library doing exactly what you ask for. Import junique-1.0.4.jar to your project as a library. It's just 10kb file.

It's manual neatly describes how to implement it on a project. For a JavaFX application, implementation would look something like this:

Make sure to import these classes to your main

import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
    public static void main(String[] args) {

String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
launch(args); // <-- This the your default JavaFX start sequence
}else{ //This else is optional. Just to free up memory if you're calling the program from a terminal.
System.exit(1);
}
}

How to enable only one instance of my application

Use android:launchMode="singleTask" or android:launchMode="singleInstance" in your manifest.xml in your activity tag

Enforce one instance of an application winform c#

You can use Mutex to ensure a single instance app.
Put the following code in the Main function of your WinForms app:

static class Program
{
static Mutex mutex = new Mutex(true, "<some_guid_or_unique_name>");

[STAThread]
static void Main()
{
if (mutex.WaitOne(TimeSpan.Zero, true))
{
// do the app code
Application.Run();

// release mutex after the form is closed.
mutex.ReleaseMutex();
mutex.Dispose();
}
}
}


Related Topics



Leave a reply



Submit