How to limit program can only run one instance.

  • Thread starter Thread starter Boki Digtal
  • Start date Start date
B

Boki Digtal

Hi All,

How to limit the c# program can only run one instance at the same
time ?

Thank you!

Best regards,
Boki.
 
Boki Digtal said:
How to limit the c# program can only run one instance at the same
time ?


using System.Threading;

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false, "Local\\" + "<app name>", out blnFirstInstance))
{
if (!blnFirstInstance)
{
MessageBox.Show("<app name> is already running", "Single Use Only", MessageBoxButtons.OK, MessageBoxIcon.Stop);
Application.Exit();
}
else
{
Application.Run(new Form1()); // or whatever your startup is...
}
}
 
using System.Threading;

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false, "Local\\" + "<app name>", out blnFirstInstance))
{
if (!blnFirstInstance)
{
MessageBox.Show("<app name> is already running", "Single Use Only", MessageBoxButtons.OK, MessageBoxIcon.Stop);
Application.Exit();
}
else
{
Application.Run(new Form1()); // or whatever your startup is...
}

}

Great, thanks!

Boki.
 
An easier way? The above is only a dozen lines of code...

Can't you get it to work, then...?

Sorry, in fact, I don't have try it yet.

If I recall correctly, there is a setting in VC6, when we assign so
many parameters to create a form. For this purpose, what we need to do
is assign a parameter as true only.

I believe your code can work, but I am just curious if there is any
other methods.

:)

Thanks!

Best regards,
Boki.
 
Sorry, in fact, I don't have try it yet.

If I recall correctly, there is a setting in VC6, when we assign so
many parameters to create a form. For this purpose, what we need to do
is assign a parameter as true only.

I believe your code can work, but I am just curious if there is any
other methods.

You could add a reference to the Microsoft.VisualBasic assembly and
use the WindowsFormsApplicationBase class which I believe has this
sort of functionality. I don't know much about it, but it *might* make
things easier for you.

Jon
 
You could add a reference to the Microsoft.VisualBasic assembly and
use the WindowsFormsApplicationBase class which I believe has this
sort of functionality. I don't know much about it, but it *might* make
things easier for you.

Jon

visual basic ... ? but I am using c# ...

Boki.
 
visual basic ... ? but I am using c# ...

Yes, but you can set a reference to the Microsoft.VisualBasic assembly and
use the (without wishing to get into a language war) "hand-holding"
functions ported over from VB6 if the code I suggested (which I pretty much
nicked from Jon anyway) is too much for you...
 
Yes, but you can set a reference to the Microsoft.VisualBasic assembly and
use the (without wishing to get into a language war) "hand-holding"
functions ported over from VB6 if the code I suggested (which I pretty much
nicked from Jon anyway) is too much for you...

OK, got it, thanks :)

Boki.
 
Try this

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.IO;

namespace SingleInstance
{
/// <summary>
/// Summary description for SingleApp.
/// </summary>
public class SingleApplication
{
public SingleApplication()
{

}
/// <summary>
/// Imports
/// </summary>

[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, int
nCmdShow);

[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr
hWnd);

[DllImport("user32.dll")]
private static extern int IsIconic(IntPtr hWnd);

/// <summary>
/// GetCurrentInstanceWindowHandle
/// </summary>
/// <returns></returns>
private static IntPtr GetCurrentInstanceWindowHandle()
{
IntPtr hWnd = IntPtr.Zero;
Process process = Process.GetCurrentProcess();
Process[] processes =
Process.GetProcessesByName(process.ProcessName);
foreach(Process _process in processes)
{
// Get the first instance that is not
this instance, has the
// same process name and was started
from the same file name
// and location. Also check that the
process has a valid
// window handle in this session to
filter out other user's
// processes.
if (_process.Id != process.Id &&
_process.MainModule.FileName
== process.MainModule.FileName &&
_process.MainWindowHandle !=
IntPtr.Zero)
{
hWnd =
_process.MainWindowHandle;
break;
}
}
return hWnd;
}
/// <summary>
/// SwitchToCurrentInstance
/// </summary>
private static void SwitchToCurrentInstance()
{
IntPtr hWnd =
GetCurrentInstanceWindowHandle();
if (hWnd != IntPtr.Zero)
{
// Restore window if minimised. Do not
restore if already in
// normal or maximised window state,
since we don't want to
// change the current state of the
window.
if (IsIconic(hWnd) != 0)
{
ShowWindow(hWnd, SW_RESTORE);
}

// Set foreground window.
SetForegroundWindow(hWnd);
}
}

/// <summary>
/// Execute a form base application if another
instance already running on
/// the system activate previous one
/// </summary>
/// <param name="frmMain">main form</param>
/// <returns>true if no previous instance is
running</returns>
public static bool Run(System.Windows.Forms.Form
frmMain)
{
if(IsAlreadyRunning())
{
//set focus on previously running app
SwitchToCurrentInstance();
return false;
}
Application.Run(frmMain);
return true;
}

/// <summary>
/// for console base application
/// </summary>
/// <returns></returns>
public static bool Run()
{
if(IsAlreadyRunning())
{
return false;
}
return true;
}

/// <summary>
/// check if given exe alread running or not
/// </summary>
/// <returns>returns true if already running</returns>
private static bool IsAlreadyRunning()
{
string strLoc =
Assembly.GetExecutingAssembly().Location;
FileSystemInfo fileInfo = new
FileInfo(strLoc);
string sExeName = fileInfo.Name;
bool bCreatedNew;

mutex = new Mutex(true, "Global\\"+sExeName,
out bCreatedNew);
if (bCreatedNew)
mutex.ReleaseMutex();

return !bCreatedNew;
}

static Mutex mutex;
const int SW_RESTORE = 9;
}
}

IN PROGRAM.CS add line
SingleApplication.Run(new frmMain());
 
using System.Threading;

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false, "Local\\" + "<app name>", out blnFirstInstance))
{
if (!blnFirstInstance)
{
MessageBox.Show("<app name> is already running", "Single Use Only", MessageBoxButtons.OK, MessageBoxIcon.Stop);
Application.Exit();
}
else
{
Application.Run(new Form1()); // or whatever your startup is...
}

}

Hi,
Please see my complete "Program.cs" below:
After I did this, it can still run more than one instance.

/////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;

namespace Ring_Buffer_Test
{

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{

bool blnFirstInstance;
using (Mutex objMutex = new Mutex(false,"Local\\" +
"BokiTesting", out blnFirstInstance))

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);


if (!blnFirstInstance)
{
MessageBox.Show("<app name> is already running", "Single
Use Only", MessageBoxButtons.OK, MessageBoxIcon.Stop);
Application.Exit();
}
else
{
Application.Run(new Form1());
}

}
}
}
////////////////


I don't know why ...

Boki.
 
Boki said:
Please see my complete "Program.cs" below:
After I did this, it can still run more than one instance.

Yes, because your "using" statement for the mutex doesn't have braces
round the code. You've effectively got:

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false,"Local\\" + "BokiTesting",
out blnFirstInstance))
{
Application.EnableVisualStyles();
}

Application.SetCompatibleTextRenderingDefault(false);

// Rest of code...

The idea is to hold the mutex for the whole of the time your app is
running.
 
Yes, because your "using" statement for the mutex doesn't have braces
round the code. You've effectively got:

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false,"Local\\" + "BokiTesting",
out blnFirstInstance))
{
Application.EnableVisualStyles();

}

Application.SetCompatibleTextRenderingDefault(false);

// Rest of code...

The idea is to hold the mutex for the whole of the time your app is
running.

Yes, you are right, thanks!

Boki.
 
Yes, because your "using" statement for the mutex doesn't have braces
round the code. You've effectively got:

bool blnFirstInstance;

using (Mutex objMutex = new Mutex(false,"Local\\" + "BokiTesting",
out blnFirstInstance))
{
Application.EnableVisualStyles();

}

Application.SetCompatibleTextRenderingDefault(false);

// Rest of code...

The idea is to hold the mutex for the whole of the time your app is
running.

Hello,

I tried same code on Vista, it seems no work. but works on XP.

Boki.
 
Boki said:
I tried same code on Vista, it seems no work. but works on XP.

Could you post a short but complete program which demonstrates the
problem on Vista?

(You haven't shown us Form1, for example.)

It should work fine on Vista.
 
Could you post a short but complete program which demonstrates the
problem on Vista?

(You haven't shown us Form1, for example.)

It should work fine on Vista.

Hi

I am using the same code here for program.cs as below:

////////////////
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]

static void Main()
{
bool firstInstance;
Mutex mutex = new Mutex(false, "Local\\" + "SPECIAL TEST
8324428", out firstInstance);

if (firstInstance)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("An instance has already been
run!","BOKI BOKI");
}

}
///////////////

However, the form1 is a normal form. I run the same .exe flie on XP,
it works well, I can see the message box.

When I copy the same .exe file on Vista environment, wow, it can has
many instances, I can't see any message box on Vista.

Boki.
 
Boki said:
I am using the same code here for program.cs as below:

////////////////
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]

static void Main()
{
bool firstInstance;
Mutex mutex = new Mutex(false, "Local\\" + "SPECIAL TEST
8324428", out firstInstance);

if (firstInstance)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("An instance has already been
run!","BOKI BOKI");
}

}
///////////////

Again, that's *not* the code we suggested - and won't always work on
XP.

You *do* want a using statement for "mutex", but covering the whole of
the rest of the code.

Look back at my reply from August 2nd.
 
Back
Top