Posted By: mot256 | Aug 2nd, 2006 @ 2:12 AM
page 1 of 2
Comments: 31 | Views: 18311
mot256
mot256
Beyond ASM... OOP
I need to know how you guys prevent another instance of the same application to startup in C#? Without using a mutex…

I know VB (at least VB.NET) has a nice event you can hook into. Not that I’m a fan of VB, except for this event and the easy way you can display a splash screen… 

Is there not some collection, list or method I can look into?

I currently use a mutex, but this is way to much code for the simple task that it must do…

Yggdrasil
Yggdrasil
Pour me a cab, 'cause I can't drink no more.
mot256 wrote:
I need to know how you guys prevent another instance of the same application to startup in C#? Without using a mutex…

I know VB (at least VB.NET) has a nice event you can hook into. Not that I’m a fan of VB, except for this event and the easy way you can display a splash screen… 

Is there not some collection, list or method I can look into?

I currently use a mutex, but this is way to much code for the simple task that it must do…



I think Mutexes are good solution - how is it too much code when you can create and check a mutex with one line of code each?
Another common method is to lock a handle to a file or just create some sort of semaphore file to say you're online.


As always, Raymond Chen has some thoughts on this:
A single-instance program is its own denial of service
PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman
Why not just check the process list for the app? 
PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman
mot256 wrote:

PerfectPhase wrote: Why not just check the process list for the app? 

I'll love to know how?


http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.getprocessesbyname.aspx
figuerres
figuerres
???
mot256 wrote:
I need to know how you guys prevent another instance of the same application to startup in C#? Without using a mutex…

I know VB (at least VB.NET) has a nice event you can hook into. Not that I’m a fan of VB, except for this event and the easy way you can display a splash screen… 

Is there not some collection, list or method I can look into?

I currently use a mutex, but this is way to much code for the simple task that it must do…




simple;  hijacck the VB library that does the work!

details to follow .... just a minute....
figuerres
figuerres
???
snips from an app I have: ==============================
using Microsoft.VisualBasic.ApplicationServices;
/// /// The main entry point for the application. ///
[STAThread]
static void Main() {
// Unhandled exceptions will be delivered to our ThreadException handler
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(AppThreadException);
// ensure only a single instance of this app runs. SingleInstanceApplication app = new SingleInstanceApplication(); app.StartupNextInstance += new StartupNextInstanceEventHandler(OnAppStartupNextInstance); }
/// /// Event handler for processing when the another application instance tries
/// to startup. Bring the previous instance of the app to the front and /// process any command-line that's needed.
/// /// Object sending this message.
/// Event argument for this message. static void OnAppStartupNextInstance(object sender, StartupNextInstanceEventArgs e)
{
// if the window is currently minimized, then restore it.
if (mainForm.WindowState == FormWindowState.Minimized) {
 mainForm.WindowState = FormWindowState.Maximized;
}
 // activate the current instance of the app, so that it's shown. mainForm.Activate();
}
 private static void AppThreadException(object source, System.Threading.ThreadExceptionEventArgs e)
{
// An unhandled exception occured somewhere in our application. Let
// the 'Global Policy' handler have a try at handling it.
try {
ExitFlag = true;
new .LogError().LogIt(e.Exception);
new .LogError().EmailIt(e.Exception);
ApplicationExceptionForm AEF = new ApplicationExceptionForm(); AEF.Ex = e.Exception; AEF.LogPath =Application.CommonAppDataPath +"\\" + Properties.Settings.Default.LogFileName; AEF.ShowDialog();
 // Something has gone very wrong - exit the application. Application.Exit();
} catch (Exception ex)
{ new .LogError().LogIt(ex);
// Something has gone wrong during HandleException (e.g. incorrect configuration of the block).
// Exit the application
string errorMsg = "An unexpected exception occured while calling HandleException. ";
errorMsg += "Please check the event log for details about the exception." + Environment.NewLine + Environment.NewLine; MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
Application.Exit();
} }
figuerres
figuerres
???
wow is that ugly!

the fancy code  paste was worse, it had extra lines in the edit window.... yow!

ok so you use the vb lib and use it's methods and setup a handler.

in the handler do what you need to do.


you also see there how I add a global error trap to log fatal errors and email them back to me.

it's a corp. type app so they know I get that data etc....

no secret stuff etc... in that part.

so far this seems to work very well in the app I am using it in.
Sven Groot
Sven Groot
You can't have everything; after all, where would you put it?
mot256 wrote:

figuerres wrote: 
using Microsoft.VisualBasic.ApplicationServices;

The assembly (microsoft.visualbasic.dll) where this namespace resides, does it get installed with .NET FW 2? Or with VS?



It's part of the core .Net Framework, no need to worry.
Sven Groot
Sven Groot
You can't have everything; after all, where would you put it?
mot256 wrote:

mot256 wrote: 
Thanx guys! This will work then!


I guess not... the SingleInstanceApplication class does not seem to be part of the Microsoft.VisualBasic.ApplicationServices namespace... well not in .NET 2 anyway...


That's because you have to create it yourself. Here's a more complete example:

using Microsoft.VisualBasic.ApplicationServices;

class SingleInstanceApplication : WindowsFormsApplicationBase
{
   public SingleInstanceApplication()
   {
      IsSingleInstance = true;
      MainForm = new Form1();
      EnableVisualStyles = true;
      Startup += new StartupEventHandler(SingleInstanceApplication_Startup);
      StartupNextInstance += new StartupNextInstanceEventHandler(SingleInstanceApplication_StartupNextInstance);
   }

   void SingleInstanceApplication_StartupNextInstance(object sender, StartupNextInstanceEventArgs e)
   {
      MessageBox.Show("Second instance.");
   }
   
   void SingleInstanceApplication_Startup(object sender, StartupEventArgs e)
   {
      MessageBox.Show("First instance.");
   }

   [STAThread]
   static void Main(string[] args)
   {
      Application.SetCompatibleTextRenderingDefault(false);
      SingleInstanceApplication app = new SingleInstanceApplication();
      app.Run(args);
   }
}

I don't think this is really "mixing VB and C#" since you're only using a VB library, not any VB code.
Ion Todirel
Ion Todirel
ban...kai
mot256 wrote:
Anyway, mixing VB and C# is like mixing CLX and VCL in the same app in Delphi... not good!
what you could do is this and for
mot256 wrote:
This will not work. Nothing prevents the user from renaming the EXE.
that you could use FileSystemWatcher (and a anonymous delegate for Renamed event) to watch if someone will change filename of the executable, i don't know how much overhead this will make?, so may be stupid. And put all code in a "public static bool IsSingleInstance { get { ... } }" property, that would be nice, minimal changes...
littleguru
littleguru
allein, allein,... allein, allein!
Interesting. I did that today. I used a Mutex and used FindWindow and ShowWindow (p/invoke) to bring the other app in front... A mutex so easy to use and works great.

The classes here are great. I remember that you could set a "property" in VB6 to avoid multiple startups of an app.