如何强制执行我的应用程序的单个实例?

如何确保我的应用程序的单个实例,并在尝试打开第二个实例时将焦点设置为它?

我试过了:

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)); } } 

这不是关注应用程序。 我怎样才能解决这个问题?

您可能希望使用Mutex ,这样可以避免以稍微不可靠的方式搜索窗口(想象您重命名主窗体或打开另一个窗体)。

 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); } } 

看起来您将Text作为参数传递给FocusWindow方法,但是在进行Contains检查时。 我敢打赌Text只是一个部分窗口标题,因此导致FindWindow失败。 尝试传递窗口句柄的全文,如:

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

它可能是由windows的相同标题引起的,因此FindWindow获取实际的Windows句柄,尝试使用EnumWindows函数而不是FindWindow。

对表单加载进行此检查是不正确的。 您应该使用Mutex来确保只有一个应用程序实例正在运行。 有关如何执行此操作以及将焦点设置为现有实例的示例,请参阅此文章 。

将此代码放在App.xaml.cs文件中:

 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