I\'ve a C# application that displays a login form when launched and displays the main form after users are authenticated. I used Mutex to restrict that only one instance of
private bool IsSingleInstance()
{
string szCurrentProcessName = this.ProductName;
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist)
{
string szProcessName = theprocess.MainModule.ModuleName.ToString();
if (szProcessName.Contains(szCurrentProcessName))
return false;
}
return true;
}
if you want limit to only one instance for a Form
, you can do something like this:
public static class LoginForm
{
private static Form _loginForm = new Form();
public static bool ShowLoginForm(){
if(_loginForm.Visible)
return false;
_loginForm.Show();
return true;
}
}
So if more then one clients will call this method, which is only possible method to show login form, in case when its already visible, it will not be executed.
If you are ok with a reference to Microsoft.VisualBasic, you can use its SingleInstance processing.
[STAThread]
static void Main(string[] args)
{
using (System.Threading.Mutex mutex = new System.Threading.Mutex(true, "MyApp.SingleInstance.Mutex", out createdNew))
{
MainForm = new MainDlg();
SingleInstanceApplication.Run(MainForm, StartupNextInstanceEventHandler);
}
}
public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
{
MainForm.Activate();
}
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
{
SingleInstanceApplication app = new SingleInstanceApplication();
app.MainForm = f;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
}
I've made some small changes:
namespace CSMutex
{
static class Program
{
[STAThread]
static void Main()
{
bool mutexCreated=true;
using(Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
{
if (mutexCreated)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Login loging = new Login();
Application.Run(loging);
Application.Run(new Main() { UserName = loging.UserName });
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
MessageBox.Show("Another instance of eCS is already running.", "eCS already running", MessageBoxButtons.OK, MessageBoxIcon.Information);
//SetForegroundWindow(process.MainWindowHandle);
break;
}
}
}
}
}
}
}
That works as expected - i.e. even when Login
form is closed (and the main application form is started) it doesn't let user run the application once again.
I've decided not to create Main
from within Login
(this is I believe how you application works) and instead I am passing parameter to Main
.
I have also made some small change to Login
so it has UserName
propert (same as Main
).