基于.Net平台应用程序唯一运行实例C#代码实现

程序

概述
本文是针对《基于.Net平台应用程序唯一运行实例实现》的补充,文章给出功能实现代码,其中SingleInstance类实现只允许一个实例运行,Program为测试主程序入口。在代码中标识说明文字。完整代码下载。
主要代码
SingleInstance.cs文件,
using System;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Runtime.InteropServices;
/*------------------------------------------------
郑佐 2006-07-01  http://blog.csdn.net/zhzuo     
--------------------------------------------------*/
namespace Zhengzuo.CSharpCode
{
    /// <summary>
    /// 只启动一个应用程序实例控制类
    /// </summary>
    public static class SingleInstance
    {
        private const int WS_SHOWNORMAL = 1;
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        //标志文件名称
        private static string runFlagFullname = null;
        //声明同步基元
        private static Mutex mutex = null; 
 
        /// <summary>
        /// static Constructor
        /// </summary>
        static SingleInstance()
        {
        }         #region api实现     
        /// <summary>
        /// 获取应用程序进程实例,如果没有匹配进程,返回Null
        /// </summary>
        /// <returns>返回当前Process实例</returns>
        public static Process GetRunningInstance()
        {                        Process currentProcess = Process.GetCurrentProcess();//获取当前进程
            //获取当前运行程序完全限定名
            string currentFileName = currentProcess.MainModule.FileName;
            //获取进程名为ProcessName的Process数组。
            Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);
            //遍历有相同进程名称正在运行的进程
            foreach (Process process in processes)
            {
                if (process.MainModule.FileName == currentFileName)
                {
                    if (process.Id != currentProcess.Id)//根据进程ID排除当前进程
                        return process;//返回已运行的进程实例
                }
            }
            return null;
        }         /// <summary>
        /// 获取应用程序句柄,设置应用程序前台运行,并返回bool值
        /// </summary>
        public static bool HandleRunningInstance(Process instance)
        {
            //确保窗口没有被最小化或最大化
            ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
            //设置真实例程为foreground window
            return SetForegroundWindow(instance.MainWindowHandle);
        }         /// <summary>
        /// 获取窗口句柄,设置应用程序前台运行,并返回bool值,重载方法
        /// </summary>
        /// <returns></returns>
        public static bool HandleRunningInstance()
        {
            Process p = GetRunningInstance();
            if (p != null)
            {
                HandleRunningInstance(p);
                return true;
            }
            return false;
        }         #endregion
        #region Mutex实现
        /// <summary>
        /// 创建应用程序进程Mutex
        /// </summary>
        /// <returns>返回创建结果,true表示创建成功,false创建失败。</returns>
        public static bool CreateMutex()
        {
            return CreateMutex(Assembly.GetEntryAssembly().FullName);
        }         /// <summary>
        /// 创建应用程序进程Mutex
        /// </summary>
        /// <param name="name">Mutex名称</param>
        /// <returns>返回创建结果,true表示创建成功,false创建失败。</returns>
        public static bool CreateMutex(string name)
        {
            bool result = false;
            mutex = new Mutex(true, name, out result);
            return result; 
        }         /// <summary>
        /// 释放Mutex
        /// </summary>
        public static void ReleaseMutex()
        {
            if (mutex != null)
            {
                mutex.Close();
            }
        }         #endregion
        #region 设置标志实现
        /// <summary>
        /// 初始化程序运行标志,如果设置成功,返回true,已经设置返回false,设置失败将抛出异常
        /// </summary>
        /// <returns>返回设置结果</returns>
        public static bool InitRunFlag()
        {
            if (File.Exists(RunFlag))
            {
                return false;
            }
            using (FileStream fs = new FileStream(RunFlag, FileMode.Create))
            {
            }
            return true;
        }         /// <summary>
        /// 释放初始化程序运行标志,如果释放失败将抛出异常
        /// </summary>
        public static void DisposeRunFlag()
        {
            if (File.Exists(RunFlag))
            {
                File.Delete(RunFlag);
            }
        } 
        /// <summary>
        /// 获取或设置程序运行标志,必须符合Windows文件命名规范
        /// 这里实现生成临时文件为依据,如果修改成设置注册表,那就不需要符合文件命名规范。
        /// </summary>
        public static string RunFlag
        {             get
            {
                if(runFlagFullname == null)
                {
                    string assemblyFullName = Assembly.GetEntryAssembly().FullName;
                    //CommonApplicationData://"C:\\Documents and Settings\\All Users\\Application Data"
                    string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
                    //"C:\\Program Files\\Common Files"
                    //string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles);
                    runFlagFullname = Path.Combine(path, assemblyFullName);
                }
                return runFlagFullname;
            }
            set
            {
                runFlagFullname = value;
            }
        }
        #endregion
    }}
Program.cs文件,
using System;
using System.Windows.Forms;
using System.Diagnostics;
using Zhengzuo.CSharpCode;
/*------------------------------------------------
  郑佐 2006-07-01  http://blog.csdn.net/zhzuo
--------------------------------------------------*/
namespace Zhengzuo.Test.WinGui
{
    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            if (args.Length == 0) //没有传送参数
            {
                Process p = SingleInstance.GetRunningInstance();
                if (p != null) //已经有应用程序副本执行
                {
                    SingleInstance.HandleRunningInstance(p);
                }
                else //启动第一个应用程序
                {
                    RunApplication();
                }
            }
            else //有多个参数
            {
                switch (args[0].ToLower())
                {
                    case "-api":
                        if (SingleInstance.HandleRunningInstance() == false)
                        {
                            RunApplication();
                        }
                        break;
                    case "-mutex":
                        if (args.Length >= 2) //参数中传入互斥体名称
                        {
                            if ( SingleInstance.CreateMutex(args[1]) )
                            {
                                RunApplication();
                                SingleInstance.ReleaseMutex();
                            }
                            else
                            {
                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。
                                MessageBox.Show("程序已经运行!");
                            }
                        }
                        else
                        {
                            if (SingleInstance.CreateMutex())
                            {
                                RunApplication();
                                SingleInstance.ReleaseMutex();
                            }
                            else
                            {
                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。
                                MessageBox.Show("程序已经运行!");
                            }
                        }
                        break;
                    case "-flag"://使用该方式需要在程序退出时调用
                        if (args.Length >= 2) //参数中传入运行标志文件名称
                        {
                            SingleInstance.RunFlag = args[1];                         
                        }
                        try
                        {
                            if (SingleInstance.InitRunFlag())
                            {
                                RunApplication();
                                SingleInstance.DisposeRunFlag();
                            }
                            else
                            {
                                //调用SingleInstance.HandleRunningInstance()方法显示到前台。
                                MessageBox.Show("程序已经运行!");
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                        break;
                    default:
                        MessageBox.Show("应用程序参数设置失败。");
                        break;
                }
            }
        }         //启动应用程序
        static void RunApplication()
        {
            Application.EnableVisualStyles();
            Application.Run(new MainForm());
        }
    }
}功能测试
功能测试类别包括下面五类,
1.本地系统同一应用程序目录;
2.本地系统同一应用程序修改运行文件名称使两次运行名称不同;
3.本地系统两次运行程序目录不同,不修改文件名称;
4.本地系统不同会话用户登录启动应用程序;
5.远程计算机程序访问启动应用程序(一个程序在远程另一个在本地)。 运行CMD命令行,
第一种调用方式:
WindowsApplication1.exe
或 WindowsApplication1.exe –api
第二种调用方式:
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,对于本文的建议或意见可在网站上留言。

时间: 2024-08-03 08:20:24

基于.Net平台应用程序唯一运行实例C#代码实现的相关文章

如何挡截基于NET平台的程序的API?

问题描述 如何挡截基于NET平台的程序的API?IAT法:NET程序只有一个mscoree.dll,而看不到user32.dll等等JMP法:一旦挡截,目标程序就出错自动退出有没有其他方法,或使用上面的方法还应注意一些什么细节? 解决方案 解决方案二:关注...解决方案三:top解决方案四:top解决方案五:.Net程序的"Hook"比普通Win32程序方便多了.通过反射机制,你可以控制它所有的行为.你可以去下ManagedSpy,这是微软的一个开源软件,拦截.Net程序事件,获取/修

跨界项目:基于Intel平台的Chromebook有望运行Windows软件

Chromebook以价格实惠而被人们所熟知,并在教育市场蚕食了Windows 10 PC的一些份额.然而即使Google已宣布将为Chrome OS带来对Android应用的支持,大家还是会遇到离不开视窗软件的时候.好消息是,跨界(CrossOver)最近搞了一个项目工具,可以让Android设备运行Windows应用的一个子集.Liliputing的报道指出,该工具并不完美.且目前暂未面向公众开放,但确已支持键鼠.DirectX 9和音频功能. 略为遗憾的是,CorssOver仅支持基于In

防火墙-php如何让程序后台运行

问题描述 php如何让程序后台运行 下面的代码是先让别人手机的能够访问网络,但是我想通过nohup在60分钟后将防火墙内的记录删除,以达到别人每60分钟必须重新连接一次网络. <?php $iipp=$_SERVER["REMOTE_ADDR"]; exec ("iptables -t nat -I PREROUTING -s $iipp -j ACCEPT"); exec ("nohup sleep 60m >/dev/null 2>&

android中gridView问题,程序无法运行

问题描述 android中gridView问题,程序无法运行 一下是代码: package com.example.android_gridview; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.view.

如何让VC和Delphi程序只运行一个实例

有些时候,我们需要我们的程序只运行一个实例,笔者自己作程序也有这样的情况,于是自已探究一番.忙活一阵后,总算小有收获,不敢独享,在天极发表出来,供大家参考. 既然是从根本上解决问题,对于Windows程序而言,就从WinMain函数入口,这是因为在VC中使用SDK的方式编写程序最透明,并且WinMain是作为VC编译器生成EXE文件的默认入口函数. WinMain的函数原型: int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, L

如何使应用程序只运行一个实例

要使应用程序只运行一个实例,一个简单的方法是在应用程序类中使用互斥量,这可以用VC下的GUIDGEN.EXE程序产生.GUIDGEN.EXE位于VC安装目录CommonTools目录下 实例 1: 新建一基于对话框的工程ex1,采用默认设置 2: 用GUIDGEN.EXE产生一个全局标志,#define one "产生的全局标志" 本例中产生的语句如下:#define one "0xbe8e2ce1, 0xdab6, 0x11d6, 0xad, 0xd0, 0x0, 0xe0

SAP的HANA云平台最终将成为其所有的基于云的应用程序的基础

SAP在Sapphire会议上宣布,SAP的HANA云平台最终将成为其所有的基于云的应用程序的基础.HANA云平台包括核心的内存数据库以及应用开发工具.分析和集成服务等. SAP是在推出HANA企业云服务不久之后于本周二宣布这个消息的.HANA企业云是一个新的服务,为用户提供在云环境中运行其SAP商务套装软件.CRM和企业仓库软件的能力.这些软件一般都是在企业内部安装的软件.SAP正在计划为主机合作伙伴提供在他们自己的数据库中很好地运行这项服务的能力. 同时,宣布HANA云平台的消息还向SAP客

Windows程序内部运行机制实例详解_C 语言

本文以孙鑫老师VC++教程中的程序为基础,详细讲解了Windows程序内部运行机制,相信可以帮助大家更好的理解Windows程序运行原理及相应的VC++程序设计.具体内容如下: 创建一个Win32应用程序步骤: 1.编写WinMain函数; 2.创建窗口(步骤如下):  a.设计(一个)窗口类(WNDCLASS)  b.注册(该)窗口类.  c.创建窗口.  d.显示并更新窗口. 3.编写消息循环. 4.编写窗口过程函数. //WinMain.cpp #include <windows.h>

利用C#线程机制实现应用程序的单实例运行

程序 只要你的程序中Main入口是如下的,则你的程序在运行时,在一个时刻只能有一个程序实例,比如Winamp就是这种,当它在运行时,再又击这个程序,是不会再运行一个实例的. 代码很简单 [STAThread]          static void Main(string[] args)          {               bool isExist;  System.Threading.Mutex mutex=new System.Threading.Mutex(true,"my