How to force C# .net app to run only one instance in Windows?

Possible Duplicate:
What is the correct way to create a single instance application?

How to force C# .net app to run only one instance in Windows?

121479 次浏览

I prefer a mutex solution similar to the following. As this way it re-focuses on the app if it is already loaded

using System.Threading;


[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);


/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
break;
}
}
}
}
}

This is what I use in my application:

static void Main()
{
bool mutexCreated = false;
System.Threading.Mutex mutex = new System.Threading.Mutex( true, @"Local\slimCODE.slimKEYS.exe", out mutexCreated );


if( !mutexCreated )
{
if( MessageBox.Show(
"slimKEYS is already running. Hotkeys cannot be shared between different instances. Are you sure you wish to run this second instance?",
"slimKEYS already running",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question ) != DialogResult.Yes )
{
mutex.Close();
return;
}
}


// The usual stuff with Application.Run()


mutex.Close();
}

to force running only one instace of a program in .net (C#) use this code in program.cs file:

public static Process PriorProcess()
// Returns a System.Diagnostics.Process pointing to
// a pre-existing process with the same name as the
// current one, if any; or null if the current process
// is unique.
{
Process curr = Process.GetCurrentProcess();
Process[] procs = Process.GetProcessesByName(curr.ProcessName);
foreach (Process p in procs)
{
if ((p.Id != curr.Id) &&
(p.MainModule.FileName == curr.MainModule.FileName))
return p;
}
return null;
}

and the folowing:

[STAThread]
static void Main()
{
if (PriorProcess() != null)
{


MessageBox.Show("Another instance of the app is already running.");
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
}

another way to single instance an application is to check their hash sums. after messing around with mutex (didn't work as i want) i got it working this way:

    [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);


public Main()
{
InitializeComponent();


Process current = Process.GetCurrentProcess();
string currentmd5 = md5hash(current.MainModule.FileName);
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (process.Id != current.Id)
{
try
{
if (currentmd5 == md5hash(process.MainModule.FileName))
{
SetForegroundWindow(process.MainWindowHandle);
Environment.Exit(0);
}
}
catch (/* your exception */) { /* your exception goes here */ }
}
}
}


private string md5hash(string file)
{
string check;
using (FileStream FileCheck = File.OpenRead(file))
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] md5Hash = md5.ComputeHash(FileCheck);
check = BitConverter.ToString(md5Hash).Replace("-", "").ToLower();
}


return check;
}

it checks only md5 sums by process id.

if an instance of this application was found, it focuses the running application and exit itself.

you can rename it or do what you want with your file. it wont open twice if the md5 hash is the same.

may someone has suggestions to it? i know it is answered, but maybe someone is looking for a mutex alternative.