標籤:
program onlyRunOne;uses Forms,Windows,SysUtils, Dialogs, Unit1 in ‘Unit1.pas‘ {Form1};{$R *.res}varmyMutex:HWND;beginmyMutex:=CreateMutex(nil,false,‘11111‘); //名稱只能全系統唯一。if WaitForSingleObject(myMutex,0)<>wait_TimeOut thenbegin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end else begin Application.MessageBox(‘已經有一個案例運行了,本案例不能運行‘,‘提示‘,mb_ok+mb_IconInformation); Application.Terminate; end;end. hMutex:=CreateMutex(nil,true,‘test1‘); if GetLastError=ERROR_ALREADY_EXISTS then begin Application.MessageBox(‘已經有一個案例運行了,本案例不能運行‘,‘提示‘,mb_ok+mb_IconInformation); Application.Terminate; Abort; end; //其中 test1 是隨便 起的字元,但如果別的程式也用這個名字 ,那2個程式也只能找開一個哦。 網上找了很多方法,很多有漏洞自己總結實驗了出來 下面是正確的 program Project1; uses Forms,Windows,SysUtils,Dialogs, Unit1 in ‘Unit1.pas‘ {Form1}, Unit2 in ‘Unit2.pas‘ {Form2}, Unit3 in ‘Unit3.pas‘ {Form3}; {$R *.res} var myMutex:HWND; begin myMutex:=CreateMutex(nil,false,‘hkOneCopy‘); if WaitForSingleObject(myMutex,0)<>wait_TimeOut then begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.CreateForm(TForm2, Form2); Application.CreateForm(TForm3, Form3); Application.Run; end else begin showmessage(‘你已經運行了程式在螢幕右下角處‘); end; end. 多執行個體指同時有同一個應用程式的多個副本在運行。同一個應用程式的多個副本可以相互獨立地同時運行,是Win32作業系統提供的一個功能。但有時,我們可能希望使用者啟動應用程式後就不再啟動它的別的副本。比如某種裝置資源的控製程序,像數據機和並行連接埠。這種情況下,用程式碼防止同時出現多個程式的副本在運行是非常必要的。 在16位的Windows中,要防止出現多個執行個體是很簡單的,因為系統變數hPrevInst可以被用來判斷是否有其他的執行個體存在。當hPrevInst變數不為0時,表示已經有別的應用程式執行個體在運行。 然而,在Win32系統中每個進程之間有R32絕緣層來彼此隔絕。因此,在Win32系統中變數hPrevInst的值總為0。另一種既適合Win32系統又適合於16位的Windows的技術,是調用FindWindow()API函數去搜尋一個已啟用的程式視窗。 Windows API 提供了函數FindWindow,可以是應用程式在啟動時檢查自己是否已經存在。 該函數在Delphi中的文法為: function FindWindow(lpClassName: PChar, lpWindowName: PChar): HWND; 其中,參數lpCalssName 是要尋找的視窗的類的名稱,參數lpWindowName是要尋找的視窗的標題(Caption)。 如果找到了相應的視窗執行個體,將返回一個非0 的該視窗控制代碼的整型值,否則返回0 。因此,只要判斷應用程式的主視窗(或者伴隨著應用程式存在而存在的視窗)是否存在就可以判斷是否已經有執行個體存在了。 例如: H := FindWindow(‘TForm1‘, nil); if H = 0 then begin ShowMessage(‘沒有發現相同的應用程式執行個體。‘); //加入載入應用程式的語句 // end else begin ShowMessage(‘應用程式已經載入。‘); SetActiveWindow(H); end;其中,參數lpWindowName的位置以Delphi保留字nil 代替,是因為視窗的標題可能在應用程式中是變化的。Windows API 函數SetActiveWindow 用於指定使用中視窗。 但是,這種方法有兩個缺陷:一是它只能基於視窗類別名或標題來搜尋視窗,但是在整個系統中視窗很可能會重複。所以,這樣做是不可靠的。而利用視窗的標題的方法也有問題,因為視窗的標題有可能發生變化(以Delphi和Word為例,每次開啟不同檔案,它們的標題都會變化),所以這種方法不可取。另一個缺陷是它每次搜尋都要遍曆所有視窗,這樣執行進來非常慢。 因此,在Win32系統中最好的解決方案是利用那些不依賴於進程的API對象,並且它們的使用也很簡單,互斥對象就可以解決這個問題。當一個應用程式首次運行時,我們就使一個互斥對象被API函數CreateMutex()建立。這個函數的參數lpName是一個唯一標識互斥對象的字串。當應用程式的執行個體要運行前,它首先要用OpenMutex()來開啟互斥對象,如果已經有一個CreateMutex()建立的互斥對象則返回非零值。另外,當試圖運行另一個程式執行個體時,使第一個執行個體被啟用。 對於這個問題,最好的解決方案是在首次運行時,利用RegisterWindowMessage()函數註冊一個訊息,並在應用程式中建立唯一的訊息標識符。然後,利用第一個執行個體對這個訊息的響應使它被第二個執行個體啟用。 這種方法阻止新執行個體的產生,但不能提前,不過較簡便。 在Project的Program檔案中program Live; uses Windows, Forms, ShellApi, SysUtils, ..; {$R *.TLB} {$R *.res} var HMutex:Hwnd; Ret:Integer; begin Application.Initialize; aTitle := ‘LiveAuction‘; Application.Title := ‘LiveAuction‘; HMutex:=CreateMutex(nil,False,Pchar(aTitle)); //建立互斥對象,名字為aTitle--‘LiveAuction‘ Ret:=GetLastError; If Ret<>ERROR_ALREADY_EXISTS Then begin //做我們正常該做的事情 end else ReleaseMutex(hMutex); //防止建立多個程式執行個體 Application.Run; end. 檢查某個exe檔案是否正在運行function exe_is_running(const exeName:String) : Boolean; //exeName:不要副檔名的Exe主檔案名 var hCurrentWindow:HWnd; szText:array[0..254] of char; begin Result := False; hCurrentWindow:=Getwindow(Application.Handle,GW_HWNDFIRST); while hCurrentWindow <> 0 do begin if Getwindowtext(hCurrentWindow,@sztext,255)>0 then begin if LowerCase(pchar(@sztext))=LowerCase(exeName) then begin Result := true; Exit; end; end; hCurrentWindow:=Getwindow(hCurrentwindow,GW_HWndNext); end; end;用法:如我們要判斷‘Live.exe‘程式是否正在運行/是否已經啟動if exe_is_running(Live) then ....else ....
[轉]Delphi中,讓程式只運行一次的方法