科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基于.Net平台应用程序唯一运行实例实现(二)

基于.Net平台应用程序唯一运行实例实现(二)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文将从实际应用角度来分析其实现原理,对三种实现方式进行测试比较,从而确定一种合适的实现方法。文章的例子使用C#语言进行描述

作者:ghost 来源:CSDN 2007年9月24日

关键字: ghost 应用程序

  • 评论
  • 分享微博
  • 分享邮件

进程互斥
在这个实现方式中需要定义一个进程同步基元,可以理解为临界资源,该资源只允许一个进程使用。根据这一点实现应用程序唯一运行实例就比较简单了。
实现步骤如下,
1.应用程序初始化访问该同步基元;
2.可以访问,说明该同步基元未被使用,也就是说没有应用程序实例运行,使用同步基元,可以继续初始化成为第一个运行实例。
3.不可以访问,说明该同步基元已被使用,也就是说已有应用程序实例运行,停止当前程序初始化,提示已有应用程序运行。
4.应用程序实例退出释放同步基元占用。

在代码中笔者使用System.Threading.Mutex类实现同步基元,实现应用程序实例之间互斥功能。Mutex默认名字取Assembly.GetEntryAssembly().FullName。
在类成员中声明同步基元,

private static Mutex mutex = null;

CreateMutex静态方法创建应用程序进程Mutex,返回创建结果为true表示创建成功,false失败。

public static bool CreateMutex()
{
    return CreateMutex(Assembly.GetEntryAssembly().FullName);
}

实现其重载方法,让用户可以自定义Mutex名字,
public static bool CreateMutex(string name)
{
    bool result = false;
    mutex = new Mutex(true, name, out result);
    return result;
}

对应的释放Mutex资源方法为,
public static void ReleaseMutex()
{
    if (mutex != null)
    {
        mutex.Close();
    }
}

在Main函数中调用下面代码实现单一应用程序实例,

if (SingleInstance.CreateMutex())
{
    Application.Run(new MainForm());
    SingleInstance.ReleaseMutex();
}
else
{
    MessageBox.Show("程序已经运行!");
}

可见,在上面的实现过程中,Mutex名字是同步基元的唯一标识,如果刚好有不同的应用程序使用了相同名称的Mutex,那不同的应用程序实例也会出现互斥现象。

运行标志
使用应用程序运行标志简单来讲就是在程序初始化的时候设置一个标志表示程序已运行,在程序运行结束的时候删除该标志。
基本步骤如下,
1.应用程序初始化检查运行标志是否已经设置;
2.发现已经设置,说明已有应用程序实例运行,停止当前程序初始化,提示已有应用程序运行。 3.发现没有设置,说明没有应用程序实例运行,继续当前程序初始化。
4.退出应用程序时删除该运行标志。

对于标志存储载体可以使用注册表、数据库或外部文件等,这里的代码使用外部文件实现。对存放标志的文件目录选择C:\Documents and Settings\All Users\Application Data,也可以是C:\Program Files\Common Files。
声明类成员标志文件名称变量,

private static string runFlagFullname = null;

初始化程序运行标志,如果设置成功,返回true,已经设置返回false,设置失败将抛出异常,

public static bool InitRunFlag()
{
    if (File.Exists(RunFlag))
    {
        return false;
    }
    using (FileStream fs = new FileStream(RunFlag, FileMode.Create))
    {
    }
    return true;
}

释放初始化程序运行标志,如果释放失败将抛出异常,
public static void DisposeRunFlag()
{
    if (File.Exists(RunFlag))
    {
        File.Delete(RunFlag);
    }
}

获取或设置程序运行标志,必须符合Windows文件命名规范,
public static string RunFlag
{
    get
    {
        if (runFlagFullname == null)
        {
            string assemblyFullName = Assembly.GetEntryAssembly().FullName;
            string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            runFlagFullname = Path.Combine(path, assemblyFullName);
        }
        return runFlagFullname;
    }
    set
    {
        runFlagFullname = value;
    }
}

在Main函数中调用下面代码实现单一应用程序实例,
if (SingleInstance.InitRunFlag())
{
    Application.Run(new MainForm());
    SingleInstance.DisposeRunFlag();
}
else
{
    MessageBox.Show("程序已经运行!");
}

可见,在上面的实现过程中,需要访问文件IO,因此有可能会出现异常,对异常需要进行具体处理。如果不同应用程序使用了相同的运行标志,也会出现进程互斥实现中存在的问题。由于运行标志存在外部载体中,如果笔者把启动的应用程序进程实例直接在Windows管理器进程列表中结束或使其产生异常,那设置的运行标志就不会销毁,应用程序就没法再次运行。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1721596

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章