How to limit program can only run one instance.

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.
 
M

Mark Rae [MVP]

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...
}
}
 
B

Boki Digtal

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.
 
B

Boki Digtal

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.
 
J

Jon Skeet [C# MVP]

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
 
B

Boki Digtal

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.
 
M

Mark Rae [MVP]

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...
 
B

Boki Digtal

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.
 
I

Ivica Muruzovic

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());
 
B

Boki

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.
 
J

Jon Skeet [C# MVP]

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.
 
B

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.

Yes, you are right, thanks!

Boki.
 
B

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.
 
J

Jon Skeet [C# MVP]

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.
 
B

Boki

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.
 
J

Jon Skeet [C# MVP]

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top