禁止程序多开,程序单一实例实现

不少应用程序有单一实例的需求,也就是同时只能开启一个实例(一般也就是一个进程)。

实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 Mutex 工具。

Mutex是互斥体,命名的互斥体可以跨进程使用,所以可以用以实现程序单一实例这个需求。相关的例子网上应该不少,不过很多给出的例子中并没有注意到一些细节,这里就完整总结下。

命名Permalink

Mutex 需要一个名字,这个名字需要唯一,一般的方式是使用一个固定的 GUID 作为名字。

对于 .NET 应用,可以通过 Assembly 上的GuidAttribute来获取。默认情况下建立工程的时候 VS 就会生成一个 GUID 给 Assembly,这样无需自己再生成一个 GUID 来使用。

另外,为了调试方面,最好给 GUID 加一个便于人识别的前缀,一般就是程序的名字。这样使用一些查看系统对象的工具时,可以方便找到这个 Mutex。

var guidAttr = (GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),typeof(GuidAttribute));
var key = string.Format("MyApp-}", guidAttr.Value);
_mutex = new Mutex(true, key);

判断Permalink

一般在程序启动的代码中进行判断,判断的方式是使用 Mutex 上的WaitOne方法。但是有两点需要注意:

  1. 程序异常退出,WaitOne 会抛出AbandonedMutexException异常,需要处理。
  2. 如果程序使用了Application.Restart来重新启动,就需要 WaitOne 等待更长的时间。这是因为Application.Restart会在程序退出前启动新程序实例,需要等待原程序完全退出释放 Mutex。
try
{
    return _mutex.WaitOne(TimeSpan.FromSeconds(1), true);
}
catch (AbandonedMutexException ex)
{
    if (ex.Mutex != null)
        ex.Mutex.ReleaseMutex();
    return true;
}

返回true则可以正常启动,否则程序已在运行。

释放Permalink

在程序退出时需要释放 Mutex。

_mutex.ReleaseMutex();

通知Permalink

有些场景下,如果应用已在运行,用户再启动应用时,需要将已在运行的应用显示给用户。如果应用已经有自己的进程间通讯方式,那就可以直接利用,如果没有,则可以使用 Windows 系统的消息广播。

P/Invoke 定义:

public const int HWND_BROADCAST = 0xffff;

[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern bool SendMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);

程序启动时注册消息:

_showMeMessage = RegisterWindowMessage(key);

判断程序已运行时广播消息:

PostMessage((IntPtr)NativeMethods.HWND_BROADCAST,_showMeMessage,IntPtr.Zero,IntPtr.Zero);

处理消息循环,显示已运行的实例:

protected override void WndProc(ref Message m)
 {
    if (m.Msg == _showMeMessage)
    {
      if (form.WindowState == FormWindowState.Minimized)
          form.WindowState = FormWindowState.Normal;

          if (!form.Visible)
              form.Show();

          var top = form.TopMost;
          form.TopMost = true;
          form.TopMost = top;
    }
    base.WndProc(ref m);
}

参考:http://sanity-free.org/143/csharp_dotnet_single_instance_application.html

时间: 2024-08-26 21:48:59

禁止程序多开,程序单一实例实现的相关文章

C#限制程序只能运行一個实例 (防多开)

//方法一:只禁止多个进程运行 using System; using System.Collections.Generic; using System.Windows.Forms; namespace DuoYeMianIE { static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static void Main() { bool ret; System.Threading.

程序单一实例实现 z

不少应用程序有单一实例的需求,也就是同时只能开启一个实例(一般也就是一个进程). 实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 Mutex 工具. Mutex是互斥体,命名的互斥体可以跨进程使用,所以可以用以实现程序单一实例这个需求.相关的例子网上应该不少,不过很多给出的例子中并没有注意到一些细节,这里就完整总结下. 命名Permalink Mutex 需要一个名字,这个名字需要唯一,一般的方式是使用一个固定的 GUID 作为名字. 对于 .NET 应用,可

C#中禁止程序多开

原文:C#中禁止程序多开 方法一.使用Mutex bool createdNew; //返回是否赋予了使用线程的互斥体初始所属权            System.Threading.Mutex instance = new System.Threading.Mutex(true, "MutexName", out createdNew); //同步基元变量            if (createdNew) //赋予了线程初始所属权,也就是首次使用互斥体            {

Android 在安装完成界面,点击打开应用程序。在应用程序点击home键,再从桌面打开程序导致产生多个实例或者说程序被重复打开

Android 在安装完成界面,点击打开应用程序.在应用程序点击home键,再从桌面打开程序导致产生多个实例或者说程序被重复打开. etong_123的专栏 - 博客频道 - CSDN.NET *http://blog.csdn.net/etong_123/article/details/22897731 android:taskAffinity与android:finishOnTaskLaunch之我见 - java豆子 - 博客园 http://www.cnblogs.com/error40

C# 防止程序多开的两种方法

互斥对象防止程序多开 private void Form1_Load(object sender, EventArgs e) { bool Exist;//定义一个bool变量,用来表示是否已经运行 //创建Mutex互斥对象 System.Threading.Mutex newMutex = new System.Threading.Mutex(true, "仅一次", out Exist); if (Exist)//如果没有运行 { newMutex.ReleaseMutex();

【转】delphi程序只允许运行一个实例的三种方法:

一.        创建互斥对象 在工程project1.dpr中创建互斥对象 Program project1 Uses Windows,Form, FrmMain in 'FrmMain.pas' {MainForm}; {$R *.res} var hAppMutex: THandle; //声明互斥变量 begin hAppMutex := CreateMutex(nil, false,’projectname’); //创建互斥对象projectname工程名称 if ( (hAppM

.net 禁止远程查看应用程序错误的详细信息,服务器上出现应用程序错误

打开页面时出现以下错误 ? "/"应用程序中的服务器错误. 运行时错误 说明:?服务器上出现应用程序错误.此应用程序的当前自定义错误设置禁止远程查看应用程序错误的详细信息(出于安全原因).但可以通过在本地服务器计算机上运行的浏览器查看.? 详细信息:?若要使他人能够在远程计算机上查看此特定错误消息的详细信息,请在位于当前 Web 应用程序根目录下的"web.config"配置文件中创建一个 <customErrors> 标记.然后应将此 <cust

程序启动的顺序以及实例变量相互赋值、传递拷贝的理解

1 public class InstanceInitializer { 2 private int i = 1; 3 private int getI() { 4 return i; 5 } 6 private int j = getI(); 7 8 9 public InstanceInitializer() 10 { 11 i = 2; 12 } 13 public static void main(String[] args) { 14 InstanceInitializer ii =

asp.net项目发布网上-当前自定义错误设置禁止远程查看应用程序

早上服务器的系统突然出错了,悲剧~ ==============异常信息:============================== 服务器上出现应用程序错误.此应用程序的当前自定义错误设置禁止远程查看应用程序 说明: 服务器上出现应用程序错误.此应用程序的当前自定义错误设置禁止查看应用程序错误的详细信息. 详细信息: 若要使他人能够从本地服务器计算机上查看此特定错误信息的详细信息,请在位于当前 Web 应用程序根目录下的“web.config”配置文件中创建一个 <customErrors>