如果你想创建一个单例应用程序,你不能在AppForm_Load 中实现Mutex 逻辑,因为当你到达那个点(这不是你的程序集的入口点/主要方法)时,这意味着你的应用程序有已经开始了。通过您的实现,您充其量可以在您注意到之前创建的另一个实例已经在运行时关闭新实例......为什么不直接“阻止”新实例的创建?
这是我的单例应用程序模板(Program 类是包含我的应用程序入口点 static void Main 的静态类):
#region Using Directives
using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
#endregion
namespace MyNamespace
{
public static class Program
{
#region Members: Static
private static Int32 s_MutexMessage;
private static Mutex s_Mutex;
#endregion
#region Properties: Static
public static Int32 MutexMessage
{
get { return s_MutexMessage; }
}
#endregion
#region Methods: Entry Point
[STAThread]
public static void Main()
{
Assembly assembly = Assembly.GetExecutingAssembly();
String assemblyGuid = ((GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0]).Value;
String mutexName = String.Format(CultureInfo.InvariantCulture, "Local\\{{{0}}}", assemblyGuid);
s_MutexMessage = NativeMethods.RegisterWindowMessage(assemblyGuid);
Boolean mutexCreated;
s_Mutex = new Mutex(true, mutexName, out mutexCreated);
if (!mutexCreated)
{
NativeMethods.PostMessage((new IntPtr(0xFFFF)), s_MutexMessage, IntPtr.Zero, IntPtr.Zero);
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ApplicationForm());
s_Mutex.ReleaseMutex();
}
#endregion
}
}
然后,在表单类中(在我的示例中为 ApplicationForm):
protected override void WndProc(ref Message m)
{
if (m.Msg == Program.MutexMessage)
{
if (NativeMethods.IsIconic(Handle))
NativeMethods.ShowWindow(Handle, 0x00000009);
NativeMethods.SetForegroundWindow(Handle);
}
base.WndProc(ref m);
}
最后,为了完整起见,这里是我的代码使用的导入,位于NativeMethods 类中(记得将其标记为internal,这是一个不容忽视的好习惯):
internal static class NativeMethods
{
#region Importations
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean IsIconic([In] IntPtr windowHandle);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = false, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean PostMessage([In, Optional] IntPtr windowHandle, [In] Int32 message, [In] IntPtr wParameter, [In] IntPtr lParameter);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean SetForegroundWindow([In] IntPtr windowHandle);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean ShowWindow([In] IntPtr windowHandle, [In] Int32 command);
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = false, SetLastError = true)]
internal static extern Int32 RegisterWindowMessage([In] String message);
}
此实现比仅基于 Mutex 对象的传统实现要长一点,需要广泛使用本机互操作,并且必须在项目中的不同类之间拆分...但我使用它模板很长时间以来很久以前,我可以肯定它是防弹的。