前言
在开发应用程序时,通常只让程序运行一个实例。所以,就要判断程序是否已经运行。
下面是我自己在项目中使用到,封装好的帮助类。有 普通的 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
{
///
/// Mutex helper
///
public class MutexHelper
{
///
/// 判断程序是否已经运行
/// 程序集实例
///
///
/// true: 程序已运行
/// false: 程序未运行
///
public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
{
string strAppName = assembly.GetName().Name;
return IsApplicationOnRun(strAppName);
}
///
/// 判断程序是否已经运行
/// 程序名称
///
///
/// true: 程序已运行
/// false: 程序未运行
///
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
{
///
/// Mutex helper
///
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);
///
/// 判断程序是否已经运行
/// 程序集实例
///
///
/// true: 程序已运行
/// false: 程序未运行
///
public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
{
string strAppName = assembly.GetName().Name;
return IsApplicationOnRun(strAppName);
}
///
/// 判断程序是否已经运行
/// 程序名称
///
///
/// true: 程序已运行
/// false: 程序未运行
///
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实现的,下面是封装的帮助类:
参考:
CreateMutex
ReleaseMutex
using System;
using System.Runtime.InteropServices;
namespace XY.Util.Helper
{
///
/// Mutex helper
///
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;
///
/// 判断程序是否已经运行
/// 程序集实例
///
///
/// true: 程序已运行
/// false: 程序未运行
///
public static bool IsApplicationOnRun(System.Reflection.Assembly assembly)
{
string strAppName = assembly.GetName().Name;
return IsApplicationOnRun(strAppName);
}
///
/// 判断程序是否已经运行
/// 程序名称
///
///
/// true: 程序已运行
/// false: 程序未运行
///
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...
}
}
}
}