Try creating a class called AppMessenger
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
namespace Messenger
{
/// <summary>
/// The problem with using command line parameters for any
applications is that a new
/// instance of the application is started. For some apps it would
be preferable if
/// there was only one instance of the app and the command line
could be forwarded
/// back to the previous instance of the app.
///
/// This can be done by looking for a previous instance of the
app, sending a
/// WM_COPYDATA message to that previous instance and exiting (if
it is found). If it
/// is not found then the application can start normally. This is
the technique used
/// by MS Word and other applications.
/// </summary>
public class AppMessenger
{
//Pick any number at random. This number will be used to
uniquely identify the message
private static int _messageID = -1163005939;
//this message will used to send the commandline to the
previous instance of the app
public const int WM_COPYDATA = 0x4A;
//API call to send WM_COPYDATA to the previous instance of the
app
[DllImport("user32", EntryPoint = "SendMessageA")]
private static extern int SendMessage(IntPtr hWnd, int wMsg,
int wParam, COPYDATASTRUCT lParam);
//all members of this class are static so do not allow an
instance to be created
private AppMessenger()
{
}
/// <summary>
/// Checks for a previous instance of this app and forwards
the
/// command line to this instance if found.
/// </summary>
/// <returns>
/// True if a previous instance was found.
/// </returns>
public static bool CheckPrevInstance()
{
IntPtr hWnd =
GetHWndOfPrevInstance(Process.GetCurrentProcess().ProcessName);
if (hWnd != IntPtr.Zero)
{
SendCommandLine(hWnd, Environment.CommandLine);
return true;
}
return false;
}
public static bool SendMessageToApp(string FileName, string
Message)
{
IntPtr hWnd =
GetHWndOfPrevInstance(GetFileNameFromFullName(FileName));
if (hWnd != IntPtr.Zero)
{
SendCommandLine(hWnd, Message);
return true;
}
//could not find process so start it
Process P = new Process();
P.StartInfo.FileName = FileName;
P.Start();
int t = Environment.TickCount + 30000;//30 second timeout
do
{
try
{
hWnd = P.MainWindowHandle;
}
catch//ignore errors
{
}
} while (hWnd == IntPtr.Zero && t <
Environment.TickCount);
if (hWnd != IntPtr.Zero)
{
SendCommandLine(hWnd, Message);
return true;
}
return false;
}
private static string GetFileNameFromFullName(string FullName)
{
int pos = FullName.LastIndexOf("\\");
if (pos >= 0)
{
return FullName.Substring(pos + 1);
}
else
{
return FullName;
}
}
/// <summary>
/// Searches for a previous instance of this app.
/// </summary>
/// <returns>
/// hWnd of the main window of the previous instance
/// or IntPtr.Zero if not found.
/// </returns>
private static IntPtr GetHWndOfPrevInstance(string
ProcessName)
{
//get the current process
Process CurrentProcess = Process.GetCurrentProcess();
//get a collection of the currently active processes with
the same name
Process[] Ps = Process.GetProcessesByName(ProcessName);
//if only one exists then there is no previous instance
if (Ps.Length > 1)
{
foreach (Process P in Ps)
{
if (P.Id != CurrentProcess.Id)//ignore this
process
{
//weed out apps that have the same exe name
but are started from a different filename.
if (P.ProcessName == ProcessName)
{
IntPtr hWnd = IntPtr.Zero;
try
{
//if process does not have a
MainWindowHandle then an exception will be thrown
//so catch and ignore the error.
hWnd = P.MainWindowHandle;
}
catch { }
//return if hWnd found.
if (hWnd.ToInt32() != 0) return hWnd;
}
}
}
}
return IntPtr.Zero;
}
/// <summary>
/// Sends command line to a previous instance of this app
/// </summary>
/// <param name="hWnd">Main Window handle of the previous
instance of this app. Found using the function
GetHWndOfPrevInstance()</param>
/// <param name="CommandLine">CommandLine or message to send</
param>
private static void SendCommandLine(IntPtr hWnd, string
CommandLine)
{
SendMessage(hWnd, WM_COPYDATA, _messageID, new
COPYDATASTRUCT(Environment.CommandLine));
}
/// <summary>
/// Processes WM_COPYDATA message sent to the main window of
this app
/// </summary>
/// <param name="m">Message sent to the main window of this
app</param>
/// <returns>Message received or null if messageID is not
valid</returns>
public static string
ProcessWM_COPYDATA(System.Windows.Forms.Message m)
{
if (m.WParam.ToInt32() == _messageID)
{
COPYDATASTRUCT st =
(COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam,
typeof(COPYDATASTRUCT));
return st.lpData;
}
return null;
}
/// <summary>
/// Structure required to be sent with the WM_COPYDATA message
/// This structure is used to contain the CommandLine
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class COPYDATASTRUCT
{
public int dwData = 0;//32 bit int to passed. Not used.
public int cbData = 0;//length of string. Will be one
greater because of null termination.
public string lpData;//string to be passed.
public COPYDATASTRUCT()
{
}
public COPYDATASTRUCT(string Data)
{
lpData = Data + "\0"; //add null termination
cbData = lpData.Length; //length includes null chr so
will be one greater
}
}
}
}
Then in your MainForm's constructor add this before
InitializeComponent:
if (Messenger.AppMessenger.CheckPrevInstance())
{
Application.Exit();
this.Close();
}
else
{
InitializeComponent();
//Command-Line
string[] Command = Environment.GetCommandLineArgs();
if (Command.Length > 1)
processCommandLine(Command);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == Messenger.AppMessenger.WM_COPYDATA)
{
string command =
Messenger.AppMessenger.ProcessWM_COPYDATA(m);
if (command != null)
{
processCommandLine(command);
return;
}
}
base.WndProc(ref m);
}
private void processCommandLine(string CommandLine)
{
//do whatever you want to do..................
}
And be sure to add a try/catch in Program.cs like so:
static void Main()
{
try
{
Application.Run(new MainForm());
}catch (Exception ex) { }
}