Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#

Enforcing Single Instance of a Hidden-Window Application

Rate me:
Please Sign up or sign in to vote.
4.44/5 (14 votes)
17 Nov 2006CPOL3 min read 79K   803   35  
Yet another article on single instance, but with a twist.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace SingleInstance
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class SingleInstanceForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.NotifyIcon notifyIcon1;
		private System.Windows.Forms.Label label2;
		private System.ComponentModel.IContainer components;

		// these are used to enforce single instance
		private static Event evnt;
		public EventSignalledHandler eventSignalled;

		[DllImport("user32.dll", CharSet=CharSet.Auto)] static extern bool SetForegroundWindow(IntPtr hWnd);

		public SingleInstanceForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

/*
			Trace.Listeners.Clear();
			TextWriterTraceListener listener = new TextWriterTraceListener( "logfile.txt" );
			Trace.Listeners.Add( listener );
			Trace.AutoFlush = true;
*/
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(SingleInstanceForm));
			this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
			this.label2 = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// notifyIcon1
			// 
			this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
			this.notifyIcon1.Text = "Click icon to exit";
			this.notifyIcon1.Visible = true;
			this.notifyIcon1.Click += new System.EventHandler(this.notifyIcon1_Click);
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(24, 80);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(232, 32);
			this.label2.TabIndex = 1;
			this.label2.Text = "Another instance tried to start";
			// 
			// SingleInstanceForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(292, 273);
			this.Controls.Add(this.label2);
			this.Name = "SingleInstanceForm";
			this.Text = "Form1";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.SingleInstanceForm_Closing);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			// this object provides single instance feature
			evnt = new Event();
				
			// already exists means another instance is running
			if ( evnt.EventAlreadyExists() )
			{
				// signal the other instance to come to foreground
				evnt.SignalEvent();
			}
			else
			{
				// otherwise start normally
				SingleInstanceForm f = new SingleInstanceForm();
				// important: access the Handle so .net will create it
				IntPtr dummy = f.Handle;
				f.eventSignalled = new EventSignalledHandler( f.evnt_EventSignalled );
				evnt.SetObject( f );

				Application.Run();
			}
		}


		// this is called by a seperate thread created by the Event class
		// Invoke does the cross thread magic for us
		public void evnt_EventSignalled()
		{
			Show();
			WindowState = FormWindowState.Normal;

			// XP will flash the 1st instance instead of bring
			// to foreground, unless the 1st instance is hidden
			// W2K brings to foreground, unless the window is hidden
			// in which case it shows but doesn't highlight title bar
			SetForegroundWindow( Handle );
		}

		private void notifyIcon1_Click(object sender, System.EventArgs e)
		{
			// click on the sys tray icon causes app to exit

			// call Environment class verion so that worker thread in
			// Event will die too.

			Environment.Exit(0);

		}

		private void SingleInstanceForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Environment.Exit( 0 );
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I live near San Diego, CA. I wouldn't recommend it unless you can handle a severe lack of cold and snow.

Comments and Discussions