使用互斥对象让程序只运行一次

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
“怎么让我的程序在运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题。本文将比较详细的说明这一问题,并给出一个较为完善的解决方案。
尽管这已经不是一个新问题了,但这里还是简要的说明一下这种技术:这的确是一个相当有用的技术,可能你经常会注意到相当多的程序在运行之后当你再次点击运行时,它只是会回到原来的窗口,而不会运行两个程序。就如同你在运行delphi时,在外部点开另一个工程文件时,delphi只是会简单的将你的当前工程置换而不是运行两个delphi。这样的好处是显而易见的:你不必担心你的程序在某些情况下被别的软件恶意运行多次而吃光内存造成当机。下面我们做进一部的说明:
熟悉win32编程的朋友(特别是多线程编程),相信对互斥对象已经相当熟悉了,它常被用做线程间同步的技术手段。这里我们使用它来防止程序重复运行。我们只是简要的提一下互斥对象,并不做深入研究:互斥对象把第一次建立它的程序作为主程序,这样我们只用检测互斥对象是否已经有主程序就判断程序是否已经运行过,这里需要涉及到一个api函数:WaitForSingleObject该函数的第一个参数为用以检测的互斥对象,第2个参数的表示函数返回结果前的滞留时间,如果改函数返回wait_TimeOut就表明互斥对象已经有了一个主程序。修改了的工程文件代码如下:(注意:以下的代码都出现在工程文件中,而不是单元文件中,并且这里都在最简单的delphi默认建立的工程基础上修改)
var
 myMutex:HWND;
begin
  myMutex:=CreateMutex(nil,false,'hkOneCopy');// CreateMutex建立互斥对象,并且给互斥对象起一个唯一的名字。
  if WaitForSingleObject(myMutex,0)<>wait_TimeOut then//程序没有被运行过
  begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
  End;
End;
下面的工作是来完善这个程序,我们不仅希望程序可以不被重复运行,而且我们也希望当用户再次点击程序可执行文件时,已经运行的程序能够做出一些响应。在这里我们希望它能够变为最上层的活动窗口以提醒用户程序已经被运行。为了达到这个目的,我们必须先获得已经运行程序的窗口句柄,以便使用SetForeGroundWindow(handle)来使程序窗口最前并激活。为了得到这个句柄,我们必须使用windows枚举函数EnumWindows来遍历windows的窗口列表,该函数可以使用一个回调函数作为参数,并用这个回调函数来对每一个系统中的窗口进行调用直到最后一个窗口或回调函数返回false为止,这个回调函数规定有两个参数(handle,Cardinal,只用注意第一个handle参数它表示由枚举函数当前遍历到的窗口句柄)。我们只要编写这个函数并在其中不断的比较当前遍历到的窗口类名和我们的程序的主窗口类名,以及比较窗口可执行文件的名称和我们程序的名称直到找到相同的为止,将这时的窗口句柄保存下来就可以了,下面的代码加上了适当的注释:
function EnumWndProc(hwnd:Thandle;param:Cardinal):bool;stdcall;
//由于用于api回调函数,请使用windows传统的参数传递方式stdcall
var
 ClassName,WinMoudleName:string;
 WinInstance:THandle;
begin
 result:=true;
 SetLength(ClassName,100);
 GetClassName(hwnd,pchar(ClassName),length(ClassName));//获得当前遍历窗口的类名
 ClassName:=pchar(ClassName);//在字符串后加结束符,确定字符串结束
 if ClassName=TForm1.ClassName then//比较
 begin
  WinInstance:=GetWindowLong(hwnd,GWL_HINSTANCE);//获得当前遍历窗口的实例
  setlength(WinMoudleName,100);
  GetModuleFileName(WinInstance,pchar(WinMoudleName),length(WinMoudleName));
  //获得当前遍历窗口的程序文件名
  WinMoudleName:=pchar(WinMoudleName);
  if WinMoudleName=MoudleName then//MoudleName为工程全局变量,自身程序的文件名
  begin
   FindHid:=hwnd;//FindHid为工程全局变量保存找到的句炳
   result:=false;//找到以后就结束遍历
  end;
 end;
end;
下面是全部的工程文件:
var
 hMutex,FindHid:HWND;
 MoudleName:string;
begin
  hMutex:=CreateMutex(nil,false,'hkOneCopy');
  if WaitForSingleObject(hMutex,0)<>wait_TimeOut then
  begin
   ……//略去的代码在前文
  end
  else
  begin
   SetLength(MoudleName,100);
   GetModuleFileName(HInstance,pchar(MoudleName),length(MoudleName));
   //获得自己程序文件名
   MoudleName:=pchar(MoudleName);
   EnumWindows(@EnumWndProc,0);//调用枚举函数
   if FindHid<>0 then
    SetForegroundWindow(FindHid);
  end;
end.
Delphi XE让应用程序同时只运行一个的方法 如果想让DELPHI应用程序在一台电脑上只运行一次,最便捷的方法就是建立互斥变量。 在工程文件中加入一下代码进行改造就可以。 {$R *.res} var hAppMutex: THandle; //声明互斥变量 begin hAppMutex := CreateMutex(nil, false,'SeiFusionDataServer'); //创建互斥对象pr... 阅读详情

相关推荐

保证Delphi程序运行一个实例的方法

然后,我们检查命名管道的创建结果,如果创建失败则表示已有实例在运行,此时我们关闭命名管道句柄并退出程序。然后,我们检查互斥体是否已经存在,如果存在则表示已有实例在运行,此时我们关闭互斥体句柄并退出程序。在Delphi中,有时我们希望确保我们的程序只能运行一个实例,以避免出现多个实例导致的问题。互斥体是一种在多线程编程中常用的同步对象,我们可以利用它来实现只允许一个实例运行的效果。在Delphi中,我们可以使用窗口类名来实现只允许一个实例运行的效果。如果存在,则发送自定义消息给已有实例,并退出程序

2301_79325657的博客 496

delphi_一次运行一个程序原代码

程序运行时有时只允许启动一个窗口,这时把这个代码你的代码中就可以了.

delphi程序运行一次

delphi编写的让程序运行一次的代码。希望喜欢

[转]Delphi中,让程序运行一次的方法

因此,在Win32系统中最好的解决方案是利用那些不依赖于进程的API对象,并且它们的使用也很简单,互斥对象就可以解决这个问题。而利用窗口的标题的方法也有问题,因为窗口的标题有可能发生变化(以Delphi和Word为例,每次打开不同文件,它们的标题都会变化),所以这种方法不可取。其中,参数lpCalssName 是要查找的窗口的类的名称,参数lpWindowName是要查找的窗口的标题(Caption)。位的Windows的技术,是调用FindWindow()API函数去搜索一个已激活的程序窗口。

martian6125 's blog! 548

程序运行一次(Delphi)

程序运行一次(Delphi)   公司开发的软件需要对串口进行操作,每次打开软件后程序自动去打开串口寻找连接到串口上的设备,但是如果用户不知道打开了两次,那么第二次打开的程序是不能正常使用的,因为对串口的操作时独占的,第一个程序独占了串口的使用权,其他程序无法再使用一个串口,当然如果PC机器上有两个串口,那第二个程序也是可以用的。为了解决这个问题,必须限制对串口操作的软件只能打开一个

2324

使用互斥对象程序运行一次(delphi)

使用互斥对象程序运行一次“怎么让我的程序运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题。本文将比较详细的说明这一问题,并给出一个较为完善的解决方案。尽管这已经不是一个新问题了,但这里还是简要的说明一下这种技术:这的确是一个相当有用的技术,可能你经常会注意到相当多的程序运行之后当你再次点击运行时,它只是会回到原来的窗口,而不会运行两个程序。就如同你在运行delphi时,在外部

记录成长的每一步 2552

[转]使用互斥对象程序运行一次(delphi)

使用互斥对象程序运行一次“怎么让我的程序运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题。本文将比较详细的说明这一问题,并给出一个较为完善的解决方案。 尽管这已经不是一个新问题了,但这里还是简要的说明一下这种技术:这的确是一个相当有用的技术,可能你经常会注意到相当多的程序运行之后当你再次点击运行时,它只是会回到原来的窗口,而不会运行两个程序。就如同你在运行delphi时,在外部点...

weixin_34273479的博客 128

使用互斥对象程序运行一次 (转)

使用互斥对象程序运行一次 (转)[@more@]使用互斥对象程序运行一次 “怎么让我的程序运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题。本文将比较详细的说明这一问题,并给出一个较为完善的解决方案。 尽...

csd3176的博客 133

c++使用CreateMuteX函数创建互斥对象单一运行实例

c++使用CreateMuteX函数创建互斥对象 #include "stdafx.h" #include <Windows.h> // 判断是否重复运行 BOOL IsAlreadyRun() { HANDLE hMutex = NULL; hMutex = ::CreateMutex(NULL, FALSE,"ch"); if (hMutex) { if (ERROR_ALREADY_EXISTS == ::GetLastError()) { return TRUE

1011

互斥对象

互斥对象属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID,一个计数器。 其中ID用于标示系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。 先讲讲互斥对象的创建,需要调用函数 CreateMutex,改函数原型如下: HANDLE CreateMutex( LPSECURITY_ATTRIBUTES

3849

MFC 程序只能运行一个实例 互斥对象

在WinApp InitInstance函数的第一行创建一个互斥对象判断对象是否为空,如果不为空,则报告,程序已经运行。返回错误。  BOOL CMyProgramApp::InitInstance()                     //CMyProgramApp是你的WinApp类名  {               HANDLE hMutex=::CreateMutex(NU

曾伟的专栏 968

通过CreateMutex创建互斥对象--使程序只能运行一个实例

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://flyxxtt.blogbus.com/logs/43472586.html 在一些程序中我们可能会希望一次只能运行程序一个实例,实现的方法有很多。今天给大家介绍一种我常用的方法,在程序开始运行使用CreateMutex来创建互斥对象,如果在这之前本程序已经运行了,互斥对象就不能成功创建,这样就能判断

2665

Windows使用互斥对象的注意事项

相关API函数介绍 HANDLECreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes,//指向安全属性的指针 BOOLbInitialOwner,//初始化互斥对象的所有者,即创建的线程是否直接拥有互斥锁 LPCTSTRlpName//指向互斥对象名的指针 ); 第三个参数,lpName是指定这把锁的名字. ...

Think88666的博客 8882

Delphi程序运行一次

使用互斥对象程序运行一次“怎么让我的程序运行时不能重复打开?”经常在论坛上看到有朋友问这方面的问题。本文将比较详细的说明这一问题,并给出一个较为完善的解决方案。尽管这已经不是一个新问题了,但这里还是简要的说明一下这种技术:这的确是一个相当有用的技术,可能你经常会注意到相当多的程序运行之后当你再次点击运行时,它只是会回到原来的窗口,而不会运行两个程序。就如同你在运行delphi时,在

随雨 3222
上一篇: 使用互斥对象让程序只运行一次
hj163
博客等级 码龄21年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值