How can I ensure a single instance of my application and to set the focus to it when attempting to open a second instance?
I tried:
public partial class Form1 : Form {
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern
IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL")]
public static extern
Boolean SetForegroundWindow(IntPtr hWnd);
private void Form1_Load(object sender, EventArgs e)
{
bool isRunning = Process.GetProcesses()
.Where(p => p.MainWindowTitle.Contains(Text))
.Count() > 1;
if (isRunning)
{
FocusWindow(Text);
Application.Exit();
}
}
public static void FocusWindow(string title)
{
SetForegroundWindow(FindWindow(null, title));
}
}
This is not focusing the application. How can I fix this?
You may want to use Mutex
instead, which avoids to search for windows in a slightly unreliable way (imagine you rename your main form or open another form instead).
bool createdNew;
Mutex m = new Mutex(true, "SomeNameHere", out createdNew);
if (!createdNew)
{
// Application already running. Call it and ask to show it's form.
IpcClientChannel clientChannel = new IpcClientChannel();
ChannelServices.RegisterChannel(clientChannel, true);
RemotingConfiguration.RegisterWellKnownClientType(typeof(ExchangeBase), "ipc://SomeNameHere/YourAppBase");
ExchangeBase Exchange = new ExchangeBase();
Exchange.ShowForm();
}
else
{
IpcServerChannel serverChannel = new IpcServerChannel("SomeNameHere");
ChannelServices.RegisterChannel(serverChannel, true);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ExchangeBase), "YourAppBase", WellKnownObjectMode.SingleCall);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new FormMain();
if (!MainForm.StopLoading)
{
Application.Run(MainForm);
// Keep the mutex reference alive until the termination of the program.
GC.KeepAlive(m);
}
}
It looks like you're passing Text
as a parameter to your FocusWindow
method, but while doing a Contains
check. I'll bet the Text is only a partial window title and thus, causing FindWindow
to fail. Try passing the full text of the window handle instead like:
var proc = Process.GetProcesses()
.Where(p => p.MainWindowTitle.Contains(Text))
.FirstOrDefault();
if (proc != null)
{
FocusWindow(p.MainWindowTitle);
Application.Exit();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With