控制程序运行实例个数——只运行一个实例

本文介绍在C/C++、C#及Java中实现Windows程序仅运行一个实例的方法。C/C++通过使用信号量对象来判断是否有实例正在运行;C#通过查询当前进程名相同的进程数量来判断;Java则提出了利用文件和端口号两种方式来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    让程序只运行一次该程序即同一时刻在内存里面运行的只有一个实例有时是必要的,有些程序运行多个实例毫无意义,比如字典程序(金山词霸)。本文介绍不同语言实现Windows程序运行单个实例的一些方法。
     c/c++

    Windows程序的4个入口函数:main,wmain, WinMain,wWinMain,在入口函数出判断程序时候有实例(进程)在运行,这里要用到进程间共享的内核对象:信号量(Mutex),相关信息会写到注册表。示例代码如下:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdShow)

  1. {
  2.      ::SetLastError(NO_ERROR); //保证GetLastError返回值不受干扰
  3.      ::CreateMutex(NULL, false, "NutexName");
  4.      if (::GetLastError() == ERROR_ALREADY_EXISTS)
  5.      {
  6.           //return;.....程序已经有实例在运行
  7.      }
  8.      //程序第一次运行,继续执行
  9. }

    说明:CreateMutex是Windows提供的系统API,当程序的一个实例创建后如果有另外程序再创建就会失败,设置错误码为

ERROR_ALREADY_EXISTS,因此可用另一个API函数GetLastError查看时候返回该错误码,确定程序时候已经有实例在运行。
     c#
     在C#中可以通过查看指定名字进程的数量来判断程序实例的个数,实例代码如下:

  1. string processName = System.Diagnostics.Process.GetCurrentProce().ProcessName;
  2. System.Diagnostics.Process[]   processes = System.Diagnostics.Process.GetProcessesByName(processName );   
  3. if(processes.Length > 1)
  4. {
  5.   //return;.....程序已经有实例在运行
  6. }
  7. //程序第一次运行,继续执行

     java
     c/c++Java与c#实现单实例程序都利用了Windows平台本身的特性,但Java的平台无关性使得它很难利用这些东西。借鉴信号量的思想,在Java程序中找到类似于信号量的替代品。
     方式一,利用文件。在程序运行时检查是否有一个特定的文件存在,如果不存在创建该文件,表明程序已经在运行,在程序退出后即删除该文件,类似于信号量对象的释放。该程序的另一个实例如果运行,检查到该文件已经存在,表明已有实例在运行,则退出。该方法的缺陷在于:程序因异常退出时可能没能删除标识文件,导致程序以后不能运行。
     方式二,鉴于文件在程序退出可能不被删除,可以占用端口号来替代信号量,当程序启动时检查该端口号是否被占用,如果没有就建立该端口好的连接,在程序退出后释放端口号。当检查到端口号已经被占用时表明有实例在运行,执行退出。该方法的缺陷是端口号可能被其他程序占用,导致判断失误而不能启动程序。因此在选端口号时应尽量避免冲突。
     由于Java难有进程间共享变量可用,以上方法都有缺陷,为减低出错率,可将两种方法共用,即只有文件存在并且端口号被占用是才判定为有实例在运行,这样可以大大减少误判的可能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值