Mutex opened in Delphi application checked in C# console application - c#

I'm launching a Delphi app and create a mutex for it like this:
var
AMutex: THandle;
function OpenMutex(const AMutexName: String): Boolean;
begin
{ Assume the Windows Mutext is already open }
Result := False;
{ Is the Mutex already open? }
if AMutex <> 0 then
exit;
{ Try to create Windows Mutex }
if CreateProgramMutex( AMutexName , AMutex) then
Result := True
else
AMutex := 0;
end;
function CreateProgramMutex( AMutexName: string; var AMutex: THandle ): boolean;
begin
{ Assume the new program mutex was created successfully. }
Result := true;
{ Attempt to create a new mutex. }
AMutex := CreateMutex(nil, False, PChar(AMutexName));
{ If we at least got a handle to the mutex... }
if (AMutex <> 0) then
begin
if GetLastError = ERROR_ALREADY_EXISTS then begin
{ Close the handle, since it already exists. }
CloseHandle(AMutex);
{ Set the return to show that it was already running. }
Result := false;
end;
end else
Result := false;
end;
And I'm trying from C#(as a beginner) to find out if my application is already running in a console app:
using System;
using System.Threading;
namespace ConsoleApplication1
{
class OneAtATimePlease
{
private static Mutex _mutex;
private static bool IsSingleInstance()
{
_mutex = new Mutex(false, "my mutex name");
// keep the mutex reference alive until the normal
//termination of the program
GC.KeepAlive(_mutex);
try
{
return _mutex.WaitOne(0, false);
}
catch (AbandonedMutexException)
{
// if one thread acquires a Mutex object
//that another thread has abandoned
//by exiting without releasing it
_mutex.ReleaseMutex();
return _mutex.WaitOne(0, false);
}
}
static void Main()
{
if (!IsSingleInstance())
Console.WriteLine("already running");
Console.ReadLine();
}
}
}
Even the Delphi app is running, IsSingleInstance is returning true. Checking the mutex in a Delphi console app using the same Delphi code is working. I'm sure that it's something obvious but I couldn't figure out what I'm doing wrong.
PS: Everything is done under the same Windows user session

You say that your aim is to check if a foreign application is running (by using a named mutex). Well, for such case you should not attempt to create a mutex object of the given name in your application but only try to open such. The reason is simple, if that foreign application uses such mutex to check if it is running by itself, you would actually steal this mutex for your application, and that foreign one would never start.
For your purpose use the TryOpenExisting class function. For example:
using System;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Mutex mutex;
if (Mutex.TryOpenExisting("My unique mutex name", out mutex)) {
try {
// with the used TryOpenExisting overload you can work with
// the mutex object here; you can wait for it or release
Console.WriteLine("Application is running!");
}
finally {
mutex.Close();
}
}
else {
Console.WriteLine("Application is NOT running!");
}
Console.ReadLine();
}
}
}

I think you need to check if the mutex was exsiting or created.
Mutex appMutex = new Mutex(true, "MyMutex", out exclusive);
if (!exclusive)
{
//Instance already existed
}

Related

How to ensure single instance application (on multiple virtual desktops)?

I'm writing a C# WinForms application that I need to ensure there's a single instance running at any given time. I thought I had it working using a Mutex.
Here is a link that I found :
How to restrict the application to just one instance.
This worked fine when I'm using a single desktop. However, when there are several virtual desktops open in Windows 10, each of those desktops can host another instance of the application.
Is there a way of limiting a single instance across ALL desktops?
If you look at Remarks section of the docs (see Note block) - you can see, that all you have to do is to prefix your mutex with "Global\". Here is an example for WinForms:
// file: Program.cs
[STAThread]
private static void Main()
{
using (var applicationMutex = new Mutex(initiallyOwned: false, name: #"Global\MyGlobalMutex"))
{
try
{
// check for existing mutex
if (!applicationMutex.WaitOne(0, exitContext: false))
{
MessageBox.Show("This application is already running!", "Already running",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}
// catch abandoned mutex (previos process exit unexpectedly / crashed)
catch (AbandonedMutexException exception) { /* TODO: Handle it! There was a disaster */ }
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}

Why does this WPF app fail to exit correcty?

I have the following code in a WPF application that shows a splash screen while a long running process happens. On all of our developer machines and testing machines this works perfectly. However on some customer machines this code is leaving the main process running.
I've tried various methods of calling a shutdown including Environment.Exit(0); and we are still seeing this process left running after it has completed.
Is there something that I have missed about how my task and the application are interacting?
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace GKUpdate
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
MainWindow oWindow;
string sPipeName;
string sGKPath;
//Call base startup
base.OnStartup(e);
//Find the GK path
sPipeName = FindArgument(e.Args, "n");
sGKPath = FindArgument(e.Args, "p");
//Check if we have a path
if (!string.IsNullOrEmpty(sGKPath))
{
//Start listening
Task.Factory.StartNew(() => ListenForSuccess(sPipeName, sGKPath));
//Show the splash window
oWindow = new MainWindow();
oWindow.Show();
}
else
{
//Exit
this.Shutdown();
}
}
private string FindArgument(string[] oArgs, string sArgumentName)
{
string sFilter;
string sArgument;
//Get the argument
sFilter = string.Format("/{0}=", sArgumentName).ToLower();
sArgument = oArgs.FirstOrDefault(x => x.ToLower().StartsWith(sFilter));
//Check if we found the argument
if (!string.IsNullOrEmpty(sArgument) && sArgument.Length > sFilter.Length)
{
//Set the argument
sArgument = sArgument.Substring(sFilter.Length).Trim('"');
}
else
{
//Set null
sArgument = null;
}
//Return the argument
return sArgument;
}
private void ListenForSuccess(string sPipeName, string sGKPath)
{
int iStatus;
try
{
//Set default status
iStatus = -1;
//Loop until the service is online
do
{
//Create the named pipe
using (NamedPipeClientStream oNamedPipe = new NamedPipeClientStream(".", sPipeName, PipeDirection.InOut))
{
//Connect the pipe allowing 5 mins
oNamedPipe.Connect(300000);
//Send the byte asking for a status report
oNamedPipe.WriteByte(0);
oNamedPipe.WaitForPipeDrain();
//Read the return
iStatus = oNamedPipe.ReadByte();
//Disconnect
oNamedPipe.Close();
}
} while (iStatus != 1);
//Check if we can do the success actions
if (iStatus == 1)
{
//Start GateKeeper using the remaining command arguments
Process.Start(sGKPath, string.Join(" ", Environment.GetCommandLineArgs().Skip(3)));
}
}
catch (Exception)
{
//Do nothing
}
finally
{
//Exit the application
Application.Current.Dispatcher.InvokeShutdown();
}
}
}
}
Check the Threads window is visual studio. One of your non-background threads is not running to completion when your application closes. I expect that you are still 'listening' at this point.
How you handle this is up to you but i recommend implementing task cancellation.
There can be multiple reason. first you have to check window Event Viewer, you will able to find actual reason.
also you should handle DispatcherUnhandledException="Application_DispatcherUnhandledException". this will show actual error.
in App.XAML :
DispatcherUnhandledException="Application_DispatcherUnhandledException"
and in App.cs:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
}
Your background thread is blocked waiting for the pipe to connect. You need to close the pipe from the foreground thread with an oNamedPipe.Close(). As Erno de Weerd says, you also need to make sure you can exit your do/while loop once the pipe aborts.
A nicer way would be to pass in a CancellationToken to the task, and use that to close the pipe when the foreground thread requests cancellation. You can then also check the cancellation state in your loop.
See How to force Task.Factory.StartNew to a background thread? to mark a Task.Factory.StartNew as a background thread so the thread is stopped as soon as all 'foreground' threads have stopped execution:
Task.Factory.StartNew(action,
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default).ContinueWith(completeAction);

How to avoid race condition when acquiring a mutex?

I am using a named system mutex to synchronise 2 processes. This is how I am currently acquiring a mutex within my application:
using System.Threading;
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
try
{
// See if a named system mutex has already been created - if it has,
// wait a short amount of time for its release.
MyMutex = Mutex.OpenExisting(MutexName);
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
// MyMutex still being held
MyMutex = null;
return false;
}
}
catch
{
// MyMutex doesn't exist so create it
MyMutex = new Mutex(true, MutexName);
}
return true;
}
OpenExisting will throw an exception if the named system mutex with MutexName doesn't exist, allowing my application to create it.
However, there seems to be a race condition here - if OpenExisting throws, there is a small window before the call to new Mutex where the other application may have acquired the mutex.
What is the best way to avoid this race condition and make this code more reliable?
A colleague mentioned that he was using CreateMutex from the Win32 Platform SDK in his code (the other process which needs to be synchronised). This doesn't seem to be natively supported by the .NET Framework, however. So I'm not sure it's the best solution for my code.
Update
Based on the answer from #David Schwartz, here is my new code:
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
bool createdNew;
MyMutex = new Mutex(true, MutexName, out createdNew);
if (createdNew)
{
// Mutex was created so ownership is guaranteed; no need to wait on it.
return true;
}
try
{
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
MyMutex = null;
return false;
}
}
catch (AbandonedMutexException)
{
// Other application was aborted, which led to an abandoned mutex.
// This is fine, as we have still successfully acquired the mutex.
}
return true;
}
There's a constructor specifically designed for this purpose. From the docs:
createdNew
Type: System.Boolean
When this method returns, contains a Boolean that is true if a local mutex was created (that is, if name is null or an empty string) or if the specified named system mutex was created; false if the specified named system mutex already existed. This parameter is passed uninitialized.

How to make my app singleton application? [duplicate]

This question already has answers here:
What is the correct way to create a single-instance WPF application?
(39 answers)
Closed 6 years ago.
I have a application but currently it is not a singleton application.
I like to make it singleton application so that its another instance does not exit at the run time .
If this can be done please reply with some sample codes .
I think the following codes will be helpful for you.
Here is the related link:
http://geekswithblogs.net/chrisfalter/archive/2008/06/06/how-to-create-a-windows-form-singleton.aspx
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
/*====================================================
*
* Add codes here to set the Winform as Singleton
*
* ==================================================*/
bool mutexIsAvailable = false;
Mutex mutex = null;
try
{
mutex = new Mutex(true, "SampleOfSingletonWinForm.Singleton");
mutexIsAvailable = mutex.WaitOne(1, false); // Wait only 1 ms
}
catch (AbandonedMutexException)
{
// don't worry about the abandonment;
// the mutex only guards app instantiation
mutexIsAvailable = true;
}
if (mutexIsAvailable)
{
try
{
Application.Run(new SampleOfSingletonWinForm());
}
finally
{
mutex.ReleaseMutex();
}
}
//Application.Run(new SampleOfSingletonWinForm());
}
}
Here are some good sample applications. Below is one possible way.
public static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName (current.ProcessName);
//Loop through the running processes in with the same name
foreach (Process process in processes)
{
//Ignore the current process
if (process.Id != current.Id)
{
//Make sure that the process is running from the exe file.
if (Assembly.GetExecutingAssembly().Location.
Replace("/", "\\") == current.MainModule.FileName)
{
//Return the other process instance.
return process;
}
}
}
//No other instance was found, return null.
return null;
}
if (MainForm.RunningInstance() != null)
{
MessageBox.Show("Duplicate Instance");
//TODO:
//Your application logic for duplicate
//instances would go here.
}
Many other possible ways. See the examples for alternatives.
First one.
Second One.
Third One.
The approach I know of is the following. The program must attempt to open a named mutex. If that mutex existed, then exit, otherwise, create the mutex. But this seems to contradict your condition that "its another instance does not exit at the run time". Anyway, maybe this too was helpful

How can I check for a running process per user session?

I have a .NET application that I only allow to run a single process at a time of, however that app is used on Citrix boxes from time to time, and as such, can be run by multiple users on the same machine.
I want to check and make sure that the application is only running once per user session, because right now if user A is running the app, then user B gets the "App already in use" message, and should not.
This is what I have now that checks for the running process:
Process[] p = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
if (p.Length > 1)
{
#if !DEBUG
allowedToOpen &= false;
errorMessage +=
string.Format("{0} is already running.{1}", Constants.AssemblyTitle, Environment.NewLine);
#endif
}
EDIT: Improved the answer according to this cw question ...
You can use a mutex for checking wether the app already runs:
using( var mutex = new Mutex( false, AppGuid ) )
{
try
{
try
{
if( !mutex.WaitOne( 0, false ) )
{
MessageBox.Show( "Another instance is already running." );
return;
}
}
catch( AbandonedMutexException )
{
// Log the fact the mutex was abandoned in another process,
// it will still get aquired
}
Application.Run(new Form1());
}
finally
{
mutex.ReleaseMutex();
}
}
Important is the AppGuid - you could make it depend on the user.
Maybe you like to read this article: the misunderstood mutex
As tanascius already say, you can use the Mutex.
On a server that is running Terminal Services, a named system mutex can have two levels of visibility. If its name begins with the prefix "Global\", the mutex is visible in all terminal server sessions. If its name begins with the prefix "Local\", the mutex is visible only in the terminal server session where it was created.
Source: msdn, Mutex Class
Just stating the obvious - although Mutex is usually considered better solution, you can still solve the single-instance-per-session issue without Mutex - just test the SessionId as well.
private static bool ApplicationIsAlreadyRunning()
{
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
// test if there's another process running in current session.
var intTotalRunningInCurrentSession = processes.Count(prc => prc.SessionId == currentProcess.SessionId);
return intTotalRunningInCurrentSession > 1;
}
Source (no Linq)
If Form1 launches non-background threads, and that Form1 exits, you've got a problem: the mutex is released but the process is still there. Something along the lines below is better IMHO:
static class Program {
private static Mutex mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createdNew = true;
mutex = new Mutex(true, #"Global\Test", out createdNew);
if (createdNew) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else {
MessageBox.Show(
"Application is already running",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
}
The mutex won't be released as long as the primary application domain is still up. And that will be around as long as the application is running.

Categories