Only one instance of application

  • Thread starter Thread starter Dmitry Karneyev
  • Start date Start date
D

Dmitry Karneyev

Hi!
I guess this question have been asked a lot of times, but please be tolerant
and if you have any ideas share it.
The question is: how to make availibale only one instance of application and
if second one is loaded it must be
close and give focus to first one.

Thanks for any advice!

Dmitry

P.S.
I've managed to do the following:
static void Main()

{

Process[] appProcess = Process.GetProcessesByName("MyApp");

if(appProcess.Length > 1)

{

MessageBox.Show("Application is already launched!);

return;

}

Application.Run(new FormMainManager());

}
 
The following code shows how to make sure that there is only one instance of
your Windows Forms application running. The code first searches for
processes with the same name as the and if one is found it makes sure that
was ran from the same location. If it decides that there is another instance
running, it shows that main window of the other instance, otherwise it runs
another instance of the main form.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;

public class OneInstnace
{
[STAThread]
public static void Main()
{
//Get the running instance.
Process instance = RunningInstance();
if (instance == null)
{
//There isn't another instance, show our form.
Application.Run (new Form());
}
else
{
//There is another instance of this process.
HandleRunningInstance(instance);
}
}
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;
}


public static void HandleRunningInstance(Process instance)
{
//Make sure the window is not minimized or maximized
ShowWindowAsync (instance.MainWindowHandle , WS_SHOWNORMAL);

//Set the real intance to foreground window
SetForegroundWindow (instance.MainWindowHandle);
}

[DllImport("User32.dll")]

private static extern bool ShowWindowAsync(
IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")] private static extern bool
SetForegroundWindow(IntPtr hWnd);
private const int WS_SHOWNORMAL = 1;
}


SOURCE:
http://www.c-sharpcorner.com/FAQ/Create1InstanceAppSC.asp

--
Greetz

Jan Tielens
________________________________
Read my weblog: http://weblogs.asp.net/jan


Dmitry Karneyev said:
Hi!
I guess this question have been asked a lot of times, but please be tolerant
and if you have any ideas share it.
The question is: how to make availibale only one instance of application and
if second one is loaded it must be
close and give focus to first one.

Thanks for any advice!

Dmitry

P.S.
I've managed to do the following:
static void Main()

{

Process[] appProcess = Process.GetProcessesByName("MyApp");

if(appProcess.Length > 1)

{

MessageBox.Show("Application is already launched!);

return;

}

Application.Run(new FormMainManager());

}
 
I used the code from that article and had a slight issue with it. (plus the
fact you get a first chance exception in Process.GetProcessesByName())

if the user clicks many times on your exe (with none currently running),
then they all check and find other instances and they all die and your
application does not start.

Had to fix it using a mutex.

Saying that see below for a reply I got the other day (in reply to the first
chance exception issue (I'm running on Win 2000)).



rollasoc,

What platform are you running this on? I think that the implementation
of GetProcessesByName is different depending on the platform (not that you
should ever know or care about it though).

However, for what you are doing, there is an easier way. I would create
a named Mutex instance, and then see if you can get a lock on it. If you
can, then you know your application is not running. If you can't get a
lock, then don't run the app. Basically, place an if block around the call
to the static Run method on the Application class, only entering if you can
obtain the Mutex.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




Jan Tielens said:
The following code shows how to make sure that there is only one instance of
your Windows Forms application running. The code first searches for
processes with the same name as the and if one is found it makes sure that
was ran from the same location. If it decides that there is another instance
running, it shows that main window of the other instance, otherwise it runs
another instance of the main form.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;

public class OneInstnace
{
[STAThread]
public static void Main()
{
//Get the running instance.
Process instance = RunningInstance();
if (instance == null)
{
//There isn't another instance, show our form.
Application.Run (new Form());
}
else
{
//There is another instance of this process.
HandleRunningInstance(instance);
}
}
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;
}


public static void HandleRunningInstance(Process instance)
{
//Make sure the window is not minimized or maximized
ShowWindowAsync (instance.MainWindowHandle , WS_SHOWNORMAL);

//Set the real intance to foreground window
SetForegroundWindow (instance.MainWindowHandle);
}

[DllImport("User32.dll")]

private static extern bool ShowWindowAsync(
IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")] private static extern bool
SetForegroundWindow(IntPtr hWnd);
private const int WS_SHOWNORMAL = 1;
}


SOURCE:
http://www.c-sharpcorner.com/FAQ/Create1InstanceAppSC.asp

--
Greetz

Jan Tielens
________________________________
Read my weblog: http://weblogs.asp.net/jan


Dmitry Karneyev said:
Hi!
I guess this question have been asked a lot of times, but please be tolerant
and if you have any ideas share it.
The question is: how to make availibale only one instance of application and
if second one is loaded it must be
close and give focus to first one.

Thanks for any advice!

Dmitry

P.S.
I've managed to do the following:
static void Main()

{

Process[] appProcess = Process.GetProcessesByName("MyApp");

if(appProcess.Length > 1)

{

MessageBox.Show("Application is already launched!);

return;

}

Application.Run(new FormMainManager());

}
 
Great info, thx!

--
Greetz

Jan Tielens
________________________________
Read my weblog: http://weblogs.asp.net/jan


rollasoc said:
I used the code from that article and had a slight issue with it. (plus the
fact you get a first chance exception in Process.GetProcessesByName())

if the user clicks many times on your exe (with none currently running),
then they all check and find other instances and they all die and your
application does not start.

Had to fix it using a mutex.

Saying that see below for a reply I got the other day (in reply to the first
chance exception issue (I'm running on Win 2000)).



rollasoc,

What platform are you running this on? I think that the implementation
of GetProcessesByName is different depending on the platform (not that you
should ever know or care about it though).

However, for what you are doing, there is an easier way. I would create
a named Mutex instance, and then see if you can get a lock on it. If you
can, then you know your application is not running. If you can't get a
lock, then don't run the app. Basically, place an if block around the call
to the static Run method on the Application class, only entering if you can
obtain the Mutex.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




Jan Tielens said:
The following code shows how to make sure that there is only one
instance
of
your Windows Forms application running. The code first searches for
processes with the same name as the and if one is found it makes sure that
was ran from the same location. If it decides that there is another instance
running, it shows that main window of the other instance, otherwise it runs
another instance of the main form.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;

public class OneInstnace
{
[STAThread]
public static void Main()
{
//Get the running instance.
Process instance = RunningInstance();
if (instance == null)
{
//There isn't another instance, show our form.
Application.Run (new Form());
}
else
{
//There is another instance of this process.
HandleRunningInstance(instance);
}
}
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;
}


public static void HandleRunningInstance(Process instance)
{
//Make sure the window is not minimized or maximized
ShowWindowAsync (instance.MainWindowHandle , WS_SHOWNORMAL);

//Set the real intance to foreground window
SetForegroundWindow (instance.MainWindowHandle);
}

[DllImport("User32.dll")]

private static extern bool ShowWindowAsync(
IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")] private static extern bool
SetForegroundWindow(IntPtr hWnd);
private const int WS_SHOWNORMAL = 1;
}


SOURCE:
http://www.c-sharpcorner.com/FAQ/Create1InstanceAppSC.asp

--
Greetz

Jan Tielens
________________________________
Read my weblog: http://weblogs.asp.net/jan


Dmitry Karneyev said:
Hi!
I guess this question have been asked a lot of times, but please be tolerant
and if you have any ideas share it.
The question is: how to make availibale only one instance of
application
and
if second one is loaded it must be
close and give focus to first one.

Thanks for any advice!

Dmitry

P.S.
I've managed to do the following:
static void Main()

{

Process[] appProcess = Process.GetProcessesByName("MyApp");

if(appProcess.Length > 1)

{

MessageBox.Show("Application is already launched!);

return;

}

Application.Run(new FormMainManager());

}
 
Dmitry Karneyev said:
Another one.
http://www.codeproject.com/csharp/singleinstance.asp

P.S. All code I've found uses user32.dll to bring main window of app to
front.
Is it possible to do the same thing using framework?

Dmitry

Dmitry

I've seen nothing in the framework "yet" that will bring the window in
another process to the foreground. That will certainly change in coming
release versions!

One would have to also consider the case of the original instance being in a
minimized state, not just hidden by another window.

The case in the work you cited has one minor problem - if the program is
executed from two different locations, both copies will run - the most
obvious case is a Release version and a Debug version (the cited work sees
that as two distinct executions).

Additionally, the use of the Mutex is exactly the right way to do it, but
the WaitOne is an unnecessary step, and there is no need to establish the
mutex as a static variable, the only requirement is that the life of the
mutex object be exactly that of the object it is trying to protect. The
mutex is a kernel object, so if the name is unique, then subsequent attempts
to create it will be seen in the Mutex(bool, string, bool) constructor (that
third param return true if this call is the first for the named object).

Here is a quick hack (no error checking, no comments, etc...) that I did
some time ago (my apologies, it is in MC++, but the xlate to C# should be
straightforward). Most of the work is done inline in the derived Form
object constructor - and it throws an exception if a multiple instance
condition is discovered. You can use the guidgen utilitiy to create the
seed for a unique name for each appliction. Then wrap the creation of the
main app form in WinMain in an exception handler, and exit without running
the form...

What you do when the second instance is discovered is very much up to you
and the requirments levied thereon. The message box that announces the
discovery of the first instance was included for demo purposes only (one
would likely remove that from a production release). I was playing with
someother things when I did this one - so I stuffed the HWND of the form
into the registry upon first successful invocation. Enumerating the windows
to find the initial instance did not seem to appealing to me at the time. In
the duplicate instance handler, I retreive the stored HWND value from the
registry, and then do a ShowWindow to bring the original form out of a
(potentially) minimized state. Next I pinned the original instance to TOP -
placing it above all other windows in the z-order, notwithstanding any that
have TOPMOST status. Be careful to not use TOPMOST, because that will force
the original window to the highest position in the z-order at that time. To
do this is almost never a user-friendly approach..

regards
roy fine


/* ******************* */
namespace SysWin32{
[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(IntPtr hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned
int uType);
[DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = Unicode)]
int ShowWindow(IntPtr hWnd, unsigned int uType);
[DllImport("user32.dll", EntryPoint = "SetWindowPos", CharSet = Unicode)]
int SetWindowPos(IntPtr, IntPtr,int x, int y, int sx, int sy, unsigned int
flags );
}


/* ******************* */
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR,int ){
Thread *curThread = System::Threading::Thread::CurrentThread;
curThread->set_Name(S"UNIQUE_THREAD_3A2B4DE1_8F68_4647_9E84_5FD4B126696A");
curThread->set_ApartmentState(System::Threading::ApartmentState::STA);
Form1 *frm = 0;
try{
frm = new Form1();
String __gc *regKeyName = S"Software\\RLFine_Testing\\MC_Singleton";
RegistryKey __gc *regKey =
Registry::CurrentUser->CreateSubKey(regKeyName);
String __gc *iVal = frm->get_Handle().ToString();
regKey->SetValue(S"AppHWND",iVal);
regKey->Close();
regKey = NULL;
Application::Run(frm);
}
catch(int /* a */){
frm = NULL;
}
return 0;
}

/* ******************* */
public __gc class Form1 : public System::Windows::Forms::Form{
private:
Mutex *mtxInstance;
....
public:
Form1(void) {
InitializeComponent();
String *tstr = S"UNIQUE_INSTANCE_DF26B334_08A0_4ae5_9260_BBD975FB6E9E";
mtxInstance = new Mutex(true,tstr,&blMutexOwner);
if(!blMutexOwner) {
SysWin32::MessageBox( 0, L"YIKES!\nhere is already an instance of this
app running!",
L"Multiple Instance Monitor", MB_OK|MB_ICONWARNING);
RegistryKey *regKey =
Registry::CurrentUser->CreateSubKey(S"Software\\RLFine_Testing\\MC_Singleton
");
Object *obj = regKey->GetValue(S"AppHWND");
String *tstr = obj->ToString();
IntPtr hwnd = IntPtr(System::Convert::ToInt64(tstr));
SysWin32::ShowWindow(hwnd,SW_RESTORE);
SysWin32::SetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
regKey->Close();
regKey = NULL;
throw 1;
}
}
 
Back
Top