只要在工程文件中作下面的处理就搞定了
var
  hmutex:hwnd;
  ret:integer;
begin
  Application.Initialize;
  hmutex:=createmutex(nil,false,'project1');
  ret:=getlasterror;
  if ret<>error_already_exists then
  begin
  Application.CreateForm(TForm1, Form1);
  end
  else
  begin
  messagedlg('程序已运行。',mtinformation,[mbok],0);
  releasemutex(hmutex);
  end;

解决方案 »

  1.   

    或者用findform(),还有对象互斥。
      

  2.   

    转贴:
    实现单实例运行的关键是判断前一实例是否存在,Win3.x中运行的程序能获知前一实
    例的句柄,从而可以方便地进行判断,但 Windows 95 是抢先式多任务系统,其程序
    的前一实例句柄恒为零,所以只有另寻其他办法。
    据说有很多方法都可解决这个问题,不过我只知道两种,下面分别加以介绍。★第一种方法:
    通过查看是否有相同窗口类名的例程存在来进行判断。API函数 FindWindow 按照指定类名和窗口名来找到窗口的句柄,该函数并不查找子窗口。FindWindow的函数原型为:HWND FindWindow(LPCTSTR lpClassName,    // address of class name
    LPCTSTR lpWindowName     // address of window name
    );    参数:lpClassName     欲查找窗口的类名。该变量的类型为以零结尾的字符串,也就是C/C++中
            的字符串类型。
    lpWindowName    窗口名。变量类型同上。返回值:若成功,返回指定窗口的句柄;否则返回NULL。如果希望得到更多的失败信息,可以调用
    GetLastError 函数。例:var
    PrevWindow:HWND;    //定义一个句柄变量begin
    Application.Initialize;    //程序初始化
    PrevWindow:=FindWindow('TForm1','运行时实例测试');
    //窗口的类名为'TForm1',窗口名为'运行时实例测试'
    //在Delphi中,窗口的类名可以从程序的TYPE区域里看到,而窗口名就是窗口的Caption属性。
    if PrevWindow<>0 then        //如果找到此窗口,说明程序已经运行了一个实例
    Begin
    MessageBox(0,"已经运行了该程序!","警告",MB_ICONWARNING+MB_OK);
    Application.Terminate;    //程序终止运行以保证只有一个实例
    end;
    Application.CreateForm(TForm1, Form1);    //否则程序继续运行
    Application.Run;
    end.//以上程序在Delphi 3.0 中通过。FindWindow函数的详细用法参见Win32 Api Help。WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
    HWND PreWindows;
        try
        {
        Application->Initialize();
    PreWindows=FindWindow("TForm1","运行实例测试");
        if(PreWindows)
    {
    MessageBox(0,"已经运行了该程序!","警告",MB_ICONWARNING+MB_OK);
    Application->Terminate();
    }
        Application->CreateForm(__classid(TForm1), &Form1);
        Application->Run();
        }
        catch (Exception &exception)
        {
        Application->ShowException(&exception);
        }
        return 0;
    }
    //以上程序在C++ Builder 1.0 中通过。★第二种方法:
    第二种方法就是利用API函数CreateMutex。CreateMutex函数用来创建一个已命名或是未命名的互斥体。CreateMutex的函数原型为:HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,    // address of security attributes 
    BOOL bInitialOwner,            // flag for initial ownership 
    LPCTSTR lpName                  // address of mutex-object name 
    );    参数说明:lpMutexAttributes    此参数指向一个SECURITY_ATTRIBUTES结构,此结构指定该互斥体的安全     
                属性,如果该参数为NULL(即为空),则以缺省的安全描述符来创建互斥
                体,并且该函数返回的句柄不能被继承。
                (此参数好象不好理解,不过在此处你只需将其设为NULL就行了!)bInitialOwner         指定互斥体对象的初始拥有者。在此处设为False。lpName              此参数指定互斥体的名字。参数类型是以NULL结尾的字符串。返回值:如果函数成功则返回互斥体的句柄,如果指定的互斥体名已经存在,则GetLastError函数返回
    ERROR_ALREADY_EXISTS。例:
    program DEL3test;uses
    Forms,Windows,SysUtils,
    DEL3unit in 'DEL3unit.pas' {Form1};{$R *.RES}Var
    hMutex:HWND;
    Ret:Integer;
    begin
    Application.Initialize;
    Application.Title := 'aaaaaa';
    hMutex:=CreateMutex(nil,False,'aaaaaa');
    Ret:=GetLastError;
    If Ret<>ERROR_ALREADY_EXISTS Then 
    Begin
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    End
    Else
    Application.MessageBox('Run Twice!','Notes!',MB_OK);
    ReleaseMutex(hMutex);
    end.//以上例子在Delphi 3.0中通过。说明:这两种方法一般来说并没有什么很大的区别,也没有在什么地方看到有关这两者的说明。
    不过我在自己的程序中正好分别试过这两种方法,发现了这两者还是有一个区别。
    如果程序中有一个启动画面,如Visual Foxpro,Delphi,wps97等等,当采用第一种方法
    时,仍然会出现启动画面,尽管在程序中我是先判断有无实例存在,然后再显示启动画面。
    为什么会这样,我也不清楚,而用第二种方法就不会出现这种情况,所以我一直都用第二
    种方法。
      

  3.   

    实现单实例运行的关键是判断前一实例是否存在,Win3.x中运行的程序能获知前 一实例的句柄,从而可以方便地进行判断,但 Windows 95 是抢先式多任务系统,其程序的前一实例句柄恒为零,所以只有另寻其他办法。目前最有效的办法是通过查看是否有相同窗口类名的例程存在来进行判断。下面介绍在Delphi中实现的方法。 1、对主窗口程序的改动: 在主窗口(即程序创建的第一个窗口)中interface节加入 
    const 
      CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息} 
      MYAPPNAME = "My Delphi Program"; 
    并在Form的定义的public节中加入 
    procedure CreateParams(var Params: TCreateParams); override; 
    Procedure RestoreRequest(var message: TMessage); message CM_RESTORE; 
    在implementation节中加入 
    {指定窗口名称} procedure TForm1.CreateParams(var Params: TCreateParams); 
    begin 
      inherited CreateParams(Params); 
      Params.WinClassName := MYAPPNAME; 
    end; {处理“恢复”消息} 
    procedure TForm1.RestoreRequest(var message: TMessage); 
    begin 
    if IsIconic(Application.Handle) = TRUE then 
      Application.Restore 
    else 
      Application.BringToFront; 
    end; 
    经过以上修改,程序的主窗口的类名已经被指定了,这是进行判断的基础。一般在程 序刚开始运行的时候进行判断,所以还要对DPR文件进行修改。 2、对DPR文件的改动 在 uses 节中添加 windows、messages这两个单元加入下列语句,注意两个文件中常 量CM_RESTORE和MYAPPNAME的定义必须一致
    const 
      CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息} 
      MYAPPNAME = "My Delphi Program"; 
    var 
      RvHandle : hWnd; 将下列语句插到程序最前部(在Application.Initialize之前) 
      RvHandle := FindWindow(MYAPPNAME, NIL); 
      if RvHandle > 0 then 
      begin 
        PostMessage(RvHandle, CM_RESTORE, 0, 0); 
        Exit; 
      end; 
    这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退 出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运行.