new_x 1 Posted October 24, 2023 Hi all I inserted the following call to the dpr file of the application to prevent the multiple instances. But did not succeed. function isOneInstance(): Boolean; Var Handle: THandle; ErrCode: DWORD; Begin Result:= False; Handle:= 0; try Handle:= CreateMutex(nil, True, 'Global\_AFB2FB05-5FA5-4C9E-9633-2353418AFF7E-HGaytt19'); if(Handle= 0) then exit(); if GetLastError() = ERROR_ALREADY_EXISTS then begin exit(); end; Result:= True; finally if(Handle<>0) then begin ReleaseMutex(Handle); CloseHandle(Handle); end; Handle:= 0; end; End; begin if(isOneInstance()) then begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end else begin Application.MessageBox('Already Running', 'WARNING', MB_OK); Application.Terminate(); end; end. Best Regards, Share this post Link to post
Kas Ob. 121 Posted October 24, 2023 6 minutes ago, new_x said: finally if(Handle<>0) then begin ReleaseMutex(Handle); CloseHandle(Handle); end; Your code is closing the handle, so how the next instance will get ERROR_ALREADY_EXISTS ?! Redesign that. 1 Share this post Link to post
new_x 1 Posted October 24, 2023 I was shocked how I did that mistake. Thanks a million for your reply. Share this post Link to post
Remy Lebeau 1393 Posted October 24, 2023 You should also set the bInitialOwner parameter to False in the CreateMutex() call. You don't need ownership of the mutex just to create it and test for its existence. You can then remove the call to ReleaseMutex() as well. Share this post Link to post
limelect 48 Posted November 27, 2023 Use OgFirst from https://github.com/TurboPack/OnGuard-VCL in dpr if TogFirst.IsFirstInstance then begin -------------- end else TogFirst.ActivateFirstInstance; Share this post Link to post
corneliusdavid 214 Posted November 28, 2023 You might like using TMutex better: Preventing Multiple Application Instances in Delphi with TMutex Share this post Link to post
aehimself 396 Posted November 28, 2023 Importing an other 3rd party library seems to be a huge overkill just to use a simple mutex. I have the following code in my .dpr file before any form creations: handle := CreateMutex(nil, True, 'MyAppName'); Try If (handle = 0) Or (GetLastError = ERROR_ALREADY_EXISTS) Then Begin // TMessageDialog.ShowDialog('Only one instance can be running at a time!', dtError); handle := FindWindow('TMyApplicationMainForm', nil); If IsWindow(handle) Then Begin ShowWindow(handle, SW_RESTORE And SW_SHOW); SetForegroundWindow(handle); SetFocus(handle); End; Exit; End; // Form creations, initialization, run here originally from .dpr Finally CloseHandle(handle); End; Works like a charm, and you only need WinApi.Windows. Share this post Link to post
Gary 18 Posted November 28, 2023 I use a similar approach as aehimself for Window programs with an addition I saw in a Holger Flick video. He created a very simple static TController class and replaced the .dpr code with a single line: begin TAppController.Run; end. This way you don't have to add code to the .dpr which I have had cause trouble in the past since Delphi edits this file as well. You can add code to the Run procedure and not worry about messing things up. TAppController = class public class procedure Run; private class function CheckSingleton: Boolean; class procedure SetFocusRunningInstance; end; class function TAppController.CheckSingleton: Boolean; begin Result := FindWindow(WINDOW_CLASS_NAME, nil) = 0; end; class procedure TAppController.SetFocusRunningInstance; begin ShowWindow(FindWindow(WINDOW_CLASS_NAME, nil), SW_SHOWMAXIMIZED); end; class procedure TAppController.Run; begin Application.Initialize; Application.MainFormOnTaskbar := True; if TAppController.CheckSingleton then begin //Add conditional defines, splash screen whatever Application.Run; end else begin TAppController.SetFocusRunningInstance; end; end; Someone else (Can't remember where) also suggested setting the main form window to something unique you need to override the CreateParams of the Main form. procedure TfrmMain.CreateParams(var Params: TCreateParams); begin inherited; StrCopy(Params.WinClassName, WINDOW_CLASS_NAME); end; 2 Share this post Link to post
Fr0sT.Brutal 900 Posted December 28, 2023 I like mutex approach more (with one little difference that I use events). It will work for any application while Findwindow is for GUI-only (or you have to create a dummy window just for that). For some apps I allow running from different paths so I'm retrieving folder of Application.ExeName and adding it to event name. 1 Share this post Link to post