科技行者

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

知识库

知识库 安全导航

至顶网软件频道.Net平台应用程序运行实例实现

.Net平台应用程序运行实例实现

  • 扫一扫
    分享文章到微信

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

   概述 在开发一些应用系统的时候,由于程序内在的一些特征,系统的某些组成子程序只允许运行一个应用程序实例,以保证业务和数据处理安全。本文将从实际应用角度来分析其实现原理,对三种实现方式进行测试比较,从而确定一种合适的实现方法。

作者:中国IT实验室 来源:中国IT实验室 2007年10月2日

关键字:

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

在本页阅读全文(共2页)

  



运行标志
使用应用程序运行标志简单来讲就是在程序初始化的时候设置一个标志表示程序已运行,在程序运行结束的时候删除该标志。
基本步骤如下,
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管理器进程列表中结束或使其产生异常,那设置的运行标志就不会销毁,应用程序就没法再次运行。

功能测试
这一节对上面的三个功能进行测试,以分析之间的区别。功能测试类别包括下面五类,
1.本地系统同一应用程序目录;
2.本地系统同一应用程序修改运行文件名称使两次运行名称不同;
3.本地系统两次运行程序目录不同,不修改文件名称;
4.本地系统不同会话用户登录启动应用程序;
5.远程计算机程序访问启动应用程序(一个程序在远程另一个在本地)。

根据代码实现细节不同,对测试的结果可能会有所不同,这里的测试结果以笔者上面几节中实现的代码为准。为了测试简单化,通过给应用程序传入测试参数,决定使用哪种方式,入口函数调用代码为,
[STAThread]
static void Main(string[] args)

        if (args.Length == 0) //没有传送参数 
       
                Process p = SingleInstance.GetRunningInstance(); 
                if (p != null) //已经有应用程序副本执行 
                        SingleInstance.HandleRunningInstance(p); 
                else //启动第一个应用程序 
                        Application.Run(new MainForm()); 
       
        else //有多个参数 
       
                switch (args[0].ToLower()) 
               
                        case "-api"
                                if (SingleInstance.HandleRunningInstance() == false
                                        Application.Run(new MainForm()); 
                                break
                        case "-mutex"
                                if (args.Length >= 2) //参数中传入互斥体名称 
                               
                                        if ( SingleInstance.CreateMutex(args[1]) ) 
                                       
                                                Application.Run(new MainForm()); 
                                                SingleInstance.ReleaseMutex(); 
                                       
                                        else 
                                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。 
                                                MessageBox.Show("程序已经运行!"); 
                               
                                else 
                               
                                        if (SingleInstance.CreateMutex()) 
                                       
                                                Application.Run(new MainForm()); 
                                                SingleInstance.ReleaseMutex(); 
                                       
                                        else 
                                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。 
                                                MessageBox.Show("程序已经运行!"); 
                               
                                break
                        case "-flag":
//使用该方式需要在程序退出时调用 
                                if (args.Length >= 2)
//参数中传入运行标志文件名称 
                                        SingleInstance.RunFlag = args[1]; 
                                try 
                                {
                                        if (SingleInstance.InitRunFlag()) 
                                       
                                                Application.Run(new MainForm()); 
                                                SingleInstance.DisposeRunFlag(); 
                                       
                                        else 
                                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。 
                                                MessageBox.Show("程序已经运行!"); 
                               
                                catch (Exception ex) 
                               
                                        MessageBox.Show(ex.ToString()); 
                               
                                break
                        default
                                MessageBox.Show("应用程序参数设置失败。"); 
                                break
               
        }
}

运行CMD命令行,
第一种调用为, WindowsApplication1.exe ?api 或 WindowsApplication1.exe
第二种调用为, WindowsApplication1.exe ?mutex 或WindowsApplication1.exe ?mutex {F140AE26-626C-42f8-BD49-45025742205E}
第三种调用为, WindowsApplication1.exe ?flag 或WindowsApplication1.exe ?flag c:\blog.csdn.net.zhzuo

测试结果,

匹配/互斥/标志 1同一目录 2修改名称 3不同目录 4不同用户 5远程访问
1同一目录 O/O/O        
2修改名称   X/O/O      
3不同目录     X/O/O    
4不同用户       #/X/O  
5远程访问         X/O/O

备注:O - 表示成功,X ? 表示失败,# - 程序第二个运行没有反应

针对远程访问的测试,需要在系统管理工具的.NET Framework 2.0 Configuration中进行设置授权该局域网路径允许访问,否则会抛出System.Security.SecurityException异常。根据测试结果可见三种实现方式适用范围不同,理想的实现是结合他们的优点进行多点判断。

更多资源
关于.NET平台应用的开发,更多的技术文章可以访问http://blog.csdn.net/zhzuo ,对于本文的建议或意见可在网站上留言。

查看本文来源

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

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

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