让程序只运行一个实例(Delphi篇)(三种方法,其中使用全局原子的方法比较有意思)

时间:2022-09-29 17:36:59

Windows 下一个典型的特征就是多任务,我们可以同时打开多个窗口进行操作,也可以同时运行程序的多个实例,比如可以打开许多个资源管理器进行文件的移动复制操作。但有时出于某种考虑(比如安全性),我们要做出一些限制,让程序只能够运行一个实例。在Delphi编程中,笔者总结出了以下几种方法:
  一、 查找窗口法
  这是最为简单的一种方法。在程序运行前用FindWindow函数查找具有相同窗口类名和标题的窗口,如果找到了,就说明已经存在一个实例。在项目源文件的初始化部分添加以下代码:

  1. Program OneApp
  2.   Uses
  3.   Forms,Windows;//(这里介绍的几种方法均需在项目源文件中添加Windows单元,以后不再重复了)
  4.   Var Hwnd:Thandle;
  5.   Begin
  6.    Hwnd:=FindWindow(‘TForm1’,‘SingleApp’);
  7.    If Hwnd=0 then
  8.    Begin
  9.    Application.Initialize;
  10.    Application.CreateForm(Tform1, Form1);
  11.    Application.Run;
  12.    End;
  13.   End;

FindWindow()函数带两个参数,其中的一个参数可以忽略,但笔者强烈建议将两个参数都用上,免得凑巧别的程序也在使用相同的类名,就得不到正确的结果了。另外,如果是在Delphi IDE窗口中运行该程序,将一次都不能运行,因为已经存在相同类名和标题的窗口:设计时的窗体。
  二、使用互斥对象
  如果觉得查找窗口的方法效率不太高的话,可以使用创建互斥对象的方法。尽管互斥对象通常用于同步连接,但用在这个地方也是非常方便的。仅用了4句代码就轻松搞定。

  1. VAR Mutex:THandle;
  2.   begin
  3.    Mutex:=CreateMutex(NIL,True,‘SingleApp’);
  4.    IF GetLastError<>ERROR_ALREADY_EXISTS THEN//如果不存在另一实例
  5.    BEGIN
  6.    Application.CreateHandle;
  7.    Application.CreateForm (TExpNoteForm, ExpNoteForm);
  8.    Application.Run;
  9.    END;
  10.    ReleaseMutex(Mutex);
  11.   end.

三、全局原子法
  我们也可以利用向系统添加全局原子的方法,来防止多个程序实例的运行。全局原子由Windows 系统负责维持,它能保证其中的每个原子都是唯一的,管理其引用计数,并且当该全局原子的引用计数为0时,从内存中清除。我们用GlobalAddAtom 函数向全局原子添加一个255个字节以内的字符串,用GlobalFindAtom来检查是否已经存在该全局原子,最后在程序结束时用GlobalDeleteAtom函数删除添加的全局原子。示例如下:

  1. Uses Windows
  2.   const iAtom=‘SingleApp’;
  3.   begin
  4.    if GlobalFindAtom(iAtom)=0 then
  5.    begin
  6.    GlobalAddAtom(iAtom);
  7.    Application.Initialize;
  8.    Application.CreateForm(TForm1,Form1);
  9.    Application.Run;
  10.    GlobalDeleteAtom(GlobalFindAtom(iAtom));
  11.    end
  12.    else
  13.    MessageBox(0,‘You can not run a second copy of this App’,‘’,mb_OK);
  14.   end.

利用全局原子的引用计数规则,我们还可以判断当前共运行了该程序的多少个实例:

  1. var i:Integer;
  2.   begin
  3.    I:=0;
  4.   while GlobalFindAtom(iAtom)<>0 do
  5.    begin
  6.    GlobalDeleteAtom(GlobalFindAtom(iAtom));
  7.    i:=i+1;
  8.    end;
  9.    ShowMessage(IntToStr(I));
  10.   end;
http://blog.csdn.net/chaijunkun/article/details/5574332

让程序只运行一个实例(Delphi篇)(三种方法,其中使用全局原子的方法比较有意思)的更多相关文章

  1. vc&plus;&plus;高级班之窗口篇&lbrack;4&rsqb;---让程序只运行一个实例

      大家都看过或者使用过类似只运行一个实例的程序,比如:QQ游戏.部分浏览器 等等! 让一个程序只运行一个实例的方法有多种,但是原理都类似,也就是在程序创建后,有窗口的程序在窗口创建前, 检查系统中是 ...

  2. VC 实现程序只运行一个实例,并激活已运行的程序

    转载:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html 进程的互斥运行:CreateMutex函数实现只运行一个程序实例 正常情况下,一个进程的 ...

  3. C&num;让应用程序只运行一个实例的几种方法

    一 判断是否有相同的实例已经运行 1 根据“Mutex”判断是否有相同的实例在运行 /// <returns>已有实例运行返回true,否则为false</returns>pu ...

  4. &lbrack;VC&rsqb;在VC&plus;&plus;中实现让程序只运行一个实例的方法且实现该实例

    方法一: 有时候在开发应用程序时,希望控制程序运行唯一的实例.例如,最常用的mp3播放软 件Winamp,由于它需要独占计算机中的音频设备,因此该程序只允许自身运行唯一的一个例程.在Visual C+ ...

  5. Java程序只运行一个实例&lbrack;转&rsqb;

    如果希望你的Java程序只能存在一个实例,可以参考下面的用法. 原文链接:http://blog.csdn.net/yaerfeng/article/details/7264729 Java没有提供这 ...

  6. VC程序只运行一个实例,并在打开多个时激活原窗口

    (一)单文档应用程序   1.在应用程序类C~~App::InitInstance()函数中判断是否已有一个应用程序实例正在运行 BOOL C~~App::InitInstance() {     . ...

  7. Winform&lpar;C&num;&rpar;限制程序只运行一个实例

    C#控制只运行开启一个程序 在这个例子中不需要调用ReleaseMutex,mutex会在程序结束时自动释放.为了防止mutex过早释放,在程序的最后调用下GC.KeepAlive (mutex). ...

  8. WPF程序只运行一个实例

    1.WPF程序在 启动窗口的构造函数执行InitializeComponent之前判断是否已经存在实例 不涉及服务器情况,可直接进行判断(不在mainwindow的构造函数中判断) // public ...

  9. 关于WPF程序只运行一个实例的方法

    找到的方法有两种: 1)http://www.cnblogs.com/liuyazhou/archive/2009/11/02/1594364.html 2)http://codereview.sta ...

随机推荐

  1. python gui之tkinter界面设计pythonic设计

    ui的设计,控件id的记录是一件比较繁琐的事情. 此外,赋值和读取数据也比较繁琐,非常不pythonic. 有没有神马办法优雅一点呢?life is short. 鉴于控件有name属性,通过dir( ...

  2. Codeforces Round &num;252 &lpar;Div&period; 2&rpar; A - Valera and Antique Items

    水题 #include <iostream> #include <set> #include <vector> #include <algorithm> ...

  3. poj3580

    区间操作的究极题,我们一个个来分析其实只有insert,delete,revolve三种没讲过insert 先把x旋到根,一开始我比较SB的,准备把新节点插入到右子树的最左节点,这显然很烦 好的方法是 ...

  4. HTML部分标签的含义&lpar;3&rpar;

    1,<a>标签,链接到另一个页面 语法:<a href="目标网址" title=“鼠标滑过显示的文本”>链接显示的文本</a> title属性 ...

  5. 设计模式(三): FACTORY工厂模式 -- 创建型模式

    1.定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类. 2.适用场景 1.第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体 ...

  6. nginx重定向规则详细介绍

    为何要使用301重定向 在网站建设中需要网页重定向的情况很多:如网页目录结构变动,网页重命名.网页的扩展名改变.网站域名改变等.如果不做重定向,用户的收藏和搜索引擎数据库中的旧地址只能让访客得到一个4 ...

  7. 《那些事之Log4j》什么是log4j?【专题一】

    Log4j 简介 在应用程序中添加日志记录总的来说基于三个目的: 监视代码中变量的变化情况,周期性的记录到文件*其他应用进行统计分析工作: 跟踪代码运行时轨迹,作为日后审计的依据: 担当集成开发环境 ...

  8. spring与junit整合测试

    1.导包4+2+aop+test 2.配置注解 3.测试

  9. 5、JDBC-元信息

    DatabaseMetaData:描述数据库的元数据对象 获取所有数据库 import org.junit.jupiter.api.AfterEach; import org.junit.jupite ...

  10. 解决Android Studio No cached version of org&period;jetbrains&period;kotlin&colon;kotlin-gradle-plugin&colon;1&period;1&period;50 available for offline mode&period;

    打开 file --> Settings... --> Build,Execution,Deployment下点击 Gradle 在Global Gradle settings 处 取消勾 ...