Dim firstInstance As Boolean
Dim safeName As String = Application.UserAppDataPath.Replace("\", "_")
Dim mtx As Mutex = New Mutex(True, safeName, firstInstance)
If Not firstInstance Then
Return
End If
Application.Run(New Form1)
...
But instead of just returning if its not the first instance, I would like to Activate the existing instance's window. I guess the question is how can I get a reference to the form in the instance already running

Single Instance app, Activate
Eddie RIveron
m_Mutex = New System.Threading.Mutex(False, m_UniqueIdentifier)
Dim bFound As Boolean = False
If m_Mutex.WaitOne(1, True) Then
'first instance
Application.Run(New MainForm)
Else
'not first instance
Try
Dim Procs() As Process = Process.GetProcesses()
Dim proc As Process
For Each proc In Procs
If proc.MainModule.FileName.Replace("\", "_") = m_UniqueIdentifier _
And proc.Id <> Process.GetCurrentProcess.Id Then
'MsgBox("another")
bFound = True
Write_File(aList)
Exit For
End If
Next proc
If bFound Then
'start this one
Dim temphwnd, x As Integer
temphwnd = proc.MainWindowHandle.ToInt32
x = ShowWindowAsync(temphwnd, SW_RESTORE)
'bring it to the top of the z-order
SetWindowPos(temphwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
'and release it
SetWindowPos(temphwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
End If
'exceptions from Process.GetProcesses are possbile
'on certain hardware running Win2kPro and using Hyperthreading
'MS is aware of this and while they are not fixing .Net1x
'they say that the fix will be in .Net2
Catch ex As ArgumentOutOfRangeException
MessageBox.Show("This program is already running." & ControlChars.CrLf & _
"To maximize performance of your computer only one instance of" & ControlChars.CrLf & _
"this program can run at a time.")
Catch ex As InvalidOperationException
MessageBox.Show("This program is already running." & ControlChars.CrLf & _
"To maximize performance of your computer only one instance of" & ControlChars.CrLf & _
"this program can run at a time.")
End Try
It works fine to check and display the first instance. I have a writeFile in there to work with a filewatcher-and will test the results- however-I would like to try the remoting route- can the same application be use for both a host and a client at the same time, using remoting It seems that there would be a problem with the port numbers.
ps- Bear with me I'm just hacking my way thru on this.
Janus007
i think if you send a message to your already open window and then recv the message with the data you want to send, then it should work
RCroft
Ex:
private void InitTrayIcon()
{
Process[] RunningProcesses = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
if(RunningProcesses.Length == 1)
{
this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.trayIcon.ContextMenu = this.contextMenu;
this.trayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("trayIcon.Icon")));
this.trayIcon.Text = "Project Builder";
this.trayIcon.Visible = true;
this.trayIcon.DoubleClick += new System.EventHandler(this.trayIcon_DoubleClick);
}
}
Werwolf13
form = new Form1();
Application.Run(form);
where form is a static instance of type Form1 declared in the class where your main method is defined. If its not the first instance you could check if form is null and if not just activate it. If it is the first instance you could just intialize it as above.
Lydon
If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
'Close this instance
Me.Close()
Else
'Code needed to load/prepare application
End If
I'm looking for the code that will let you switch to the other instance... The object Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName) contains all the handles necessary to grab another running app, I just can't remember the proper object method to do it...
markep12
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace SingleInstance
{
public sealed class SingleApplication
{
private SingleApplication()
{
}
[DllImport("user32.Dll")]
private static extern int EnumWindows(EnumWinCallBack callBackFunc, int lParam);
[DllImport("User32.Dll")]
private static extern void GetWindowText(int hWnd, StringBuilder str, int nMaxCount);
[DllImport("user32.dll",EntryPoint="SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd,Int32 nCmdShow);
private static bool EnumWindowCallBack(int hwnd, int lParam)
{
windowHandle = (IntPtr)hwnd;
StringBuilder sbuilder = new StringBuilder(256);
GetWindowText((int)windowHandle, sbuilder, sbuilder.Capacity);
string strTitle = sbuilder.ToString();
if(strTitle == sTitle)
{
ShowWindow(windowHandle, SW_RESTORE);
SetForegroundWindow(windowHandle);
return false;
}
return true;
}
/// <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())
{
sTitle = frmMain.Text;
//set focus on previously running app
EnumWindows (new EnumWinCallBack(EnumWindowCallBack), 0);
return false;
}
Application.Run(frmMain);
return true;
}
public static bool Run(System.Windows.Forms.ApplicationContext context)
{
if(IsAlreadyRunning())
{
sTitle = context.MainForm.Text;
//set focus on previously running app
EnumWindows (new EnumWinCallBack(EnumWindowCallBack), 0);
return false;
}
Application.Run(context);
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.GetEntryAssembly().Location;
FileSystemInfo fileInfo = new FileInfo(strLoc);
string sExeName = fileInfo.Name;
mutex = new Mutex(true, sExeName);
if (mutex.WaitOne(0, false))
{
return false;
}
return true;
}
private static Mutex mutex;
private const int SW_RESTORE = 9;
private static string sTitle;
private static IntPtr windowHandle;
private delegate bool EnumWinCallBack(int hwnd, int lParam);
}
}
I think I found this code on codeproject.com, but I added the method Run(ApplicationContext) and fixed a bug in IsAlreadyRunning() where it has to check the entry assembly and not the executing assembly.
manba
If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
'Display an optional message to the user
'MsgBox("More than one instance of the application is not allowed.")
'Make the current instance active
AppActivate(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)(0).Id)
'Close this instance
Me.Close()
Else
'Code needed to load/prepare application
End If
So there you go. One If-Then statement with two required lines of code. :)
Mauro Araujo
form = new Form1();
where form is a static instance of type Form1 declared in the class where your main method is defined. If its not the first instance you could check if form is null and if not just activate it.
Daniel Leom
But do you need the reference
What I mean is: You say that you need to pass the command line arguements from instance 2 to instance 1 before instance 2 is closed. You could do this with a file or the registry. You might have the app "watch" for a file or registry key to appear; this would be created only when instance 2 closes. Whenever the app sees this file (or key) get created (or changed) it reads the value (which is your command line args) and then deletes or empties the file/key.
This would be a simple work-around to avoid the messy remoting; especially since you don't really need to "control" the other instance - just give it some info.
Chrismar
Inquisitve2
General
Dim firstInstance As Boolean
Dim safeName As String = Application.UserAppDataPath.Replace("\", "_")
Dim mtx As Mutex = New Mutex(True, safeName, firstInstance)
If Not firstInstance Then
Dim formUrl As String = "tcp://localhost:1313/form1"
Dim connection As Object = RemotingServices.Connect(GetType(Form1), formUrl)
Dim otherForm1 As Form1 = DirectCast(connection, Form1)
otherForm1.TopMost = True
otherForm1.Activate()
otherForm1.WindowState = FormWindowState.Normal
otherForm1.TopMost = False
Return
End If
_form1Instance = New Form1
ChannelServices.RegisterChannel(New TcpChannel(1313))
RemotingServices.Marshal(_form1Instance, "form1")
Application.Run(_form1Instance)