zoukankan      html  css  js  c++  java
  • C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper

    前言

    在开发应用程序时,通常只让程序运行一个实例。所以,就要判断程序是否已经运行。

    下面是我自己在项目中使用到,封装好的帮助类。有 普通的 C# 应用程序 和 Windows CE 和 Windows Mobile 应用程序使用的方法。

    主要是通过 System.Threading.Mutex 类 和 Win32 API 来实现,下面就是各自的代码,调用示例在最后面。

    普通 C# 应用程序

    主要是 Windows 窗体应用程序和控制台程序。

    1. 使用 System.Threading.Mutex 类

    参考:Mutex 类(System.Threading)

    using System.Threading;
    
    namespace XY.Util.Helper
    {
        /// <summary>
        /// Mutex helper
        /// </summary>
    	public class MutexHelper
        {
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assembly">程序集实例</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
            {
                string strAppName = assembly.GetName().Name;
                return IsApplicationOnRun(strAppName);
            }
    
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assemblyName">程序名称</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(string assemblyName)
            {
                bool ret = false;
                //第一个参数:true--给调用线程赋予互斥体的初始所属权  
                //第一个参数:互斥体的名称  
                //第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true
                Mutex mutex = new Mutex(true, assemblyName, out ret);
                return !ret;
            }
    	}
    }
    

    2. 使用 Win32 API

    using System;
    using System.Runtime.InteropServices;
    
    namespace XY.Util.Helper
    {
        /// <summary>
        /// Mutex helper
        /// </summary>
    	public class MutexHelper
        {
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr OpenMutex(uint dwDesiredAccess, bool bInitialOwner, string lpName);
    
            [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);
    
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assembly">程序集实例</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
            {
                string strAppName = assembly.GetName().Name;
                return IsApplicationOnRun(strAppName);
            }
    
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assemblyName">程序名称</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(string assemblyName)
            {
                bool ret = false;
    
                if (OpenMutex(0x1F0001, false, assemblyName) == IntPtr.Zero)
                {
                    CreateMutex(IntPtr.Zero, false, assemblyName);
                    ret = true;
                }
    
                return ret;
            }
    	}
    }
    

    Windows CE | Windows Mobile 应用程序

    在 Windows CE 和 Windows Mobile 中实现,是通过 Win32 API实现的,下面是封装的帮助类:

    参考:

    using System;
    using System.Runtime.InteropServices;
    
    namespace XY.Util.Helper
    {
        /// <summary>
        /// Mutex helper
        /// </summary>
    	public class MutexHelper
    	{
    		[DllImport("coredll.dll", EntryPoint = "CreateMutex", SetLastError = true)]
    		public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool bInitialOwner, string lpName);
    
    		[DllImport("coredll.dll", EntryPoint = "ReleaseMutex", SetLastError = true)]
    		public static extern bool ReleaseMutex(IntPtr hMutex);
    
    		private const int ERROR_ALREADY_EXISTS = 0183;
    
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assembly">程序集实例</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
            {
                string strAppName = assembly.GetName().Name;
                return IsApplicationOnRun(strAppName);
            }
    
            /// <summary>
            /// 判断程序是否已经运行
            /// <param name="assemblyName">程序名称</param>
            /// </summary>
            /// <returns>
            /// true: 程序已运行
            /// false: 程序未运行
            /// </returns>
            public static bool IsApplicationOnRun(string assemblyName)
            {
                IntPtr hMutex = CreateMutex(IntPtr.Zero, true, assemblyName);
                if (hMutex == IntPtr.Zero)
                {
                    throw new ApplicationException("Failure creating mutex: " + Marshal.GetLastWin32Error().ToString("X"));
                }
                if (Marshal.GetLastWin32Error() == ERROR_ALREADY_EXISTS)
                {
                    ReleaseMutex(hMutex);
                    return true;
                }
                return false;
            }
    	}
    }
    

    示例代码

    调用示例:

    using System;
    using System.Reflection;
    using XY.Util.Helper;
    
    namespace MutexTest
    {
        static class Program
        {
            [MTAThread]
            static void Main(string[] args)
            {
                bool run;
    
                //方式一
                run = MutexHelper.IsApplicationOnRun("ApplicationName");
    
                //方式二
                run = MutexHelper.IsApplicationOnRun(Assembly.GetExecutingAssembly());
    
                if (run)
                {
                    // application is running...
                    // Exit.
                }
                else
                {
                    // start application ...
                    // startup...
                }
            }
        }
    }
    
  • 相关阅读:
    Expedition(POJ 2431)
    spring异步@Async原理和注意问题
    springBoot事件
    spring定时任务原理
    BeanFactory和FactoryBean的区别
    Spring容器启动流程——源码阅读分析
    spring循环依赖
    spring相关的问题和原因分析
    zookeeper原理
    zookeeper的使用
  • 原文地址:https://www.cnblogs.com/seayxu/p/5807197.html
Copyright © 2011-2022 走看看