I'm trying to use the mutex method for only allowing one instance of my app to run. That is - I only want a max of one instance for all users on a machine. I've read through the various other threads on this issue and the solution seems straightforward enough but in testing I can't get my second instance to not run. Here is my code...
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// check that there is only one instance of the control panel running...
bool createdNew = true;
using (Mutex instanceMutex = new Mutex(true, #"Global\ControlPanel", out createdNew))
{
if (!createdNew)
{
Application.Current.Shutdown();
return;
}
}
base.OnStartup(e);
}
}
You're also disposing the mutex in the same method, so the mutex only lives for the duration of the method. Store the mutex in a static field, and keep it alive for the duration of your application.
Here is my new code which has the answer provided by #Willem van Rumpt (and #OJ)...
public partial class App : Application
{
private Mutex _instanceMutex = null;
protected override void OnStartup(StartupEventArgs e)
{
// check that there is only one instance of the control panel running...
bool createdNew;
_instanceMutex = new Mutex(true, #"Global\ControlPanel", out createdNew);
if (!createdNew)
{
_instanceMutex = null;
Application.Current.Shutdown();
return;
}
base.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
if(_instanceMutex != null)
_instanceMutex.ReleaseMutex();
base.OnExit(e);
}
}
You're destroying the Mutex immediately after you've created it and tested it. You need to keep the Mutex reference alive for lifetime of your application.
Make the Mutex a member/field of your Application class.
Release the mutex when your application shuts down.
As extension sample:
public static class Extension
{
private static Mutex mutex;
public static bool IsOneTimeLaunch(this Application application, string uniqueName = null)
{
var applicationName = Path.GetFileName(Assembly.GetEntryAssembly().GetName().Name);
uniqueName = uniqueName ?? string.Format("{0}_{1}_{2}",
Environment.MachineName,
Environment.UserName,
applicationName);
application.Exit += (sender, e) => mutex.Dispose();
bool isOneTimeLaunch;
mutex = new Mutex(true, uniqueName, out isOneTimeLaunch);
return isOneTimeLaunch;
}
}
App Class:
protected override void OnStartup(StartupEventArgs e)
{
if (this.IsOneTimeLaunch())
{
base.OnStartup(e);
}
else
{
this.Shutdown();
}
}
I can suggest a much cleaner approach that also introduce the useful concept of overriding the Main method in WPF application. Also, if using your solution you take a look at the task manager, you will notice that the new instance actually reach the execution state (you can see a new process created in the list of task) and then suddenly close. The approach proposed in the post that follows will avoid this drawback too.
http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html
I was told to implement this mutex approach on an already developed WPF application that we had. The work around to the problem with using override of the OnStart() that I found was in
App.g.cs
This file is located in
obj\x86\debug\
and contains the main() function, so you just simply put this piece of code in your main function.
bool isOnlyInstance = false;
Mutex m = new Mutex(true, #"WpfSingleInstanceApplication", out isOnlyInstance);
if (!isOnlyInstance)
{
MessageBox.Show("Another Instance of the application is already running.",
"Alert",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
return;
}
GC.KeepAlive(m);
but for this you need to keep the BUILD ACTION of your app.xaml set to ApplicationDefinition
NOTE: This might not be the best way, since I'm a beginner. (please tell me if there's something I should change)
I did this from this link just add the given class and a single line in you App.Xaml.cs
http://wpfsingleinstance.codeplex.com/
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
WpfSingleInstance.Make(); //added this is the function of that class
base.OnStartup(e);
}
}
Related
I've a window application which consists of splash screen, login window, and the main window. As what I've searched, most of the single instance application checking is at the application startup (App.xaml.cs):
public partial class App: Application
{
private static Mutex mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
Application.Current.Shutdown();
}
base.OnStartup(e);
}
}
For my case, I want to allow only one user with different login ID to be logged into the application for once in the same local computer. How can I implement the method above in Login.xaml.cs or MainWindow.xaml.cs, since the method above is done in App.xaml.cs?
By comparing process main title window:
public void SingleInstanceHandler()
{
Process[] procList = Process.GetProcesses();
foreach(Process proc in procList)
{
if (!string.IsNullOrEmpty(proc.MainWindowTitle))
{
if (proc.MainWindowTitle == windowTitle)
{
//Show relevant message
Application.Current.Shutdown();
}
}
}
}
This can be placed not only in App.xaml.cs, but also in Login.xaml.cs or MainWindow.xaml.cs
I have a unmanaged application which opens at runtime my managed application.
- Each time the unmanaged aplication is being executed , it opens a new instance of my application .
I have to somehow do this scenario:
-When the unmanaged application is being executed for the first time, my managed aplication should run fine,but if the user tries to open again the unmanaged application , those managed instances should be in "standby" mode and if the first managed application which is currently running is closed , one of the standby instances should be "resumed" .
As I've seen so far , I should be using mutex :
public Form1()
{
InitializeComponent();
if (!IsSingleInstance())
{
this.Close();
return;
}
}
private static Mutex _mutex;
private static bool IsSingleInstance()
{
_mutex = new Mutex(false, "MyApp");
GC.KeepAlive(_mutex);
try
{
return _mutex.WaitOne(0, false);
}
catch (AbandonedMutexException)
{
_mutex.ReleaseMutex();
return _mutex.WaitOne(0, false);
}
}
protected override void OnClosing(CancelEventArgs e)
{
if (_mutex != null)
{
_mutex.ReleaseMutex();
}
}
But ofcourse , the code only checks if another istance is running and if it does..then it will close it.
What can I do?
Thanks,
I'd rather put the lock in Main in Program.cs.
static void Main()
{
Mutex mutex = new Mutex(false, "MyApp");
if (mutex.WaitOne())
{
try
{
Application.Run(new Form1());
}
finally
{
mutex.ReleaseMutex();
}
}
}
I have a service that creates a thread with a loop that should run until the mutex is signalled by another process. I have the following in my service code
private readonly Mutex _applicationRunning = new Mutex(false, #"Global\HsteMaintenanceRunning");
protected override void OnStart(string[] args)
{
new Thread(x => StartRunningThread()).Start();
}
internal void StartRunningThread()
{
while (_applicationRunning.WaitOne(1000))
{
FileTidyUp.DeleteExpiredFile();
_applicationRunning.ReleaseMutex();
Thread.Sleep(1000);
}
}
Now I have a console application that should claim the mutex and force the while loop to be exited
var applicationRunning = Mutex.OpenExisting(#"Global\HsteMaintenanceRunning");
if (applicationRunning.WaitOne(15000))
{
Console.Write("Stopping");
applicationRunning.ReleaseMutex();
Thread.Sleep(10000);
}
When the console application tries to open the mutex I get the error "The wait completed due to an abandoned mutex." Whats wrong here?
I recommend that you use the Service's built-in stop signal rather than a mutex. The mutex class is more appropriate for managing exclusive access to a shared resource, which is not what's going on here. You could also use a system event but since services already have a built-in mechanism for signaling when they're stopping, why not use it?
Your service's code would look like this:
bool _stopping = false;
Thread _backgroundThread;
protected override void OnStart(string[] args)
{
_backgroundThread = new Thread(x => StartRunningThread());
_backgroundThread.Start();
}
protected override void OnStop()
{
_stopping = true;
_backgroundThread.Join(); // wait for background thread to exit
}
internal void StartRunningThread()
{
while (!stopping)
{
FileTidyUp.DeleteExpiredFile();
Thread.Sleep(1000);
}
}
Then, your console application would need to use the framework's ServiceController class to send the shut down message to your service:
using System.ServiceProcess;
...
using (var controller = new ServiceController("myservicename")) {
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(15.0));
}
Are the normal winform applications in C# multiple instance support by default ?
How to prevent this creation of multiple instance in WPF applications ?
yes they are
see this msdn article
EDIT: or even better: codeproject article
1- Yes, you can execute many instance of your application. With some code, you can avoid it.
2- in App.xaml.cs, you can override some methods and use a Mutex :
public partial class App : Application
{
private Mutex instanceMutex = null;
protected override void OnStartup(StartupEventArgs e)
{
Boolean createdNew;
this.instanceMutex = new Mutex(true, "MyApplication", out createdNew);
if (!createdNew)
{
this.instanceMutex = null;
Application.Current.Shutdown();
return;
}
base.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
if (this.instanceMutex != null)
{
this.instanceMutex.ReleaseMutex();
}
base.OnExit(e);
}
}
Application c:\pinkPanther.exe is running and it is application i wrote in c#.
Some other application starts c:\pinkPanther.exe purpleAligator greenGazelle OrangeOrangutan and i would like not to start new instance of c:\pinkPanther.exe with these arguments, but to currently running c:\pinkPanther.exe register it and react to it somehow.
How to do it?
EDIT!!!: i'm very sorry about pinkPanther.exe and ruzovyJeliman.exe that caused the confusion - i translated question from my native language and missed it :(
This is assuming your application is a WinForms app, as that will make it easier to keep it open. This is a very simple example, but it will show you the basics:
Add a reference to Microsoft.VisualBasic.
Create an Application class inheriting from WindowsFormsApplicationBase. This base class contains built-in mechanisms for creating a single-instance application and responding to repeated calls on the commandline with new arguments:
using Microsoft.VisualBasic.ApplicationServices;
//omitted namespace
public class MyApp : WindowsFormsApplicationBase {
private static MyApp _myapp;
public static void Run( Form startupform ) {
_myapp = new MyApp( startupform );
_myapp.StartupNextInstance += new Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventHandler( _myapp_StartupNextInstance );
_myapp.Run( Environment.GetCommandLineArgs() );
}
static void _myapp_StartupNextInstance( object sender, Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e ) {
//e.CommandLine contains the new commandline arguments
// this is where you do what you want with the new commandline arguments
// if you want it the window to come to the front:
e.BringToForeground = true;
}
private MyApp( Form mainform ) {
this.IsSingleInstance = true;
this.MainForm = mainform;
}
}
All you have to change in Main() is call Run() on your new class rather than Application.Run():
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
MyApp.Run( new MyMainForm() );
}
}
WindowsFormsApplicationBase has some other capabilities you can explore, as well.
To communicate with the other instance of the application, you need some sort of inter-process communication. Apparently, WCF is the recommended form of IPC in .Net. You can do that with code like this (using WPF, but WinForms would be similar):
[ServiceContract]
public interface ISingletonProgram
{
[OperationContract]
void CallWithArguments(string[] args);
}
class SingletonProgram : ISingletonProgram
{
public void CallWithArguments(string[] args)
{
// handle the arguments somehow
}
}
public partial class App : Application
{
private readonly Mutex m_mutex;
private ServiceHost m_serviceHost;
private static string EndpointUri =
"net.pipe://localhost/RuzovyJeliman/singletonProgram";
public App()
{
// find out whether other instance exists
bool createdNew;
m_mutex = new Mutex(true, "RůžovýJeliman", out createdNew);
if (!createdNew)
{
// other instance exists, call it and exit
CallService();
Shutdown();
return;
}
// other instance does not exist
// start the service to accept calls and show UI
StartService();
// show the main window here
// you can also process this instance's command line arguments
}
private static void CallService()
{
var factory = new ChannelFactory<ISingletonProgram>(
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), EndpointUri);
var singletonProgram = factory.CreateChannel();
singletonProgram.CallWithArguments(Environment.GetCommandLineArgs());
}
private void StartService()
{
m_serviceHost = new ServiceHost(typeof(SingletonProgram));
m_serviceHost.AddServiceEndpoint(
typeof(ISingletonProgram),
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None),
EndpointUri);
m_serviceHost.Open();
}
protected override void OnExit(ExitEventArgs e)
{
if (m_serviceHost != null)
m_serviceHost.Close();
m_mutex.Dispose();
base.OnExit(e);
}
}