How can I apply one instance of my application?

How can I provide a single instance of my application and set focus on it when I try 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 does not focus the application. How can i fix this?

+4
source share
5 answers

Instead, you can use Mutex , which avoids looking for windows in a slightly unreliable way (imagine that you rename your main form or open another form).

 bool createdNew; Mutex m = new Mutex(true, "SomeNameHere", out createdNew); if (!createdNew) { // Application already running. Call it and ask to show it 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); } } 
+6
source

It looks like you are passing Text as a parameter to your FocusWindow method, but when performing a Contains check. I bet that the text is just a partial window title, and thus causes FindWindow crash. Try passing the full text of the window handle, for example:

 var proc = Process.GetProcesses() .Where(p => p.MainWindowTitle.Contains(Text)) .FirstOrDefault(); if (proc != null) { FocusWindow(p.MainWindowTitle); Application.Exit(); } 
+2
source

This is probably due to the same window name, so FindWindow gets the actual window handle, trying to use the EnumWindows function instead of FindWindow.

+1
source

Performing this form load validation check is incorrect. You must use Mutex to ensure that only one instance of the application is running. See this article for an example of how to do this, as well as focusing on an existing instance.

+1
source

Put this code in the App.xaml.cs file:

 using System.Runtime.InteropServices; #region SetWindowPos Definitions [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); static readonly IntPtr HWND_TOP = new IntPtr(0); static readonly IntPtr HWND_BOTTOM = new IntPtr(1); const UInt32 SWP_NOSIZE = 0x0001; const UInt32 SWP_NOMOVE = 0x0002; const UInt32 SWP_NOZORDER = 0x0004; const UInt32 SWP_NOREDRAW = 0x0008; const UInt32 SWP_NOACTIVATE = 0x0010; const UInt32 SWP_FRAMECHANGED = 0x0020; const UInt32 SWP_SHOWWINDOW = 0x0040; const UInt32 SWP_HIDEWINDOW = 0x0080; const UInt32 SWP_NOCOPYBITS = 0x0100; const UInt32 SWP_NOOWNERZORDER = 0x0200; const UInt32 SWP_NOSENDCHANGING = 0x0400; #endregion #region OnStartup protected override void OnStartup(StartupEventArgs e) { // Only allow one instance of the application Process thisProc = Process.GetCurrentProcess(); Process[] processes = Process.GetProcessesByName(thisProc.ProcessName); if (processes.Length > 1) { Application.Current.Shutdown(); SetWindowPos(processes[1].MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); SetWindowPos(processes[1].MainWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); } else { base.OnStartup(e); } } #endregion 
0
source

Source: https://habr.com/ru/post/1390906/


All Articles