Forum > General

Unique Instance Terminate Application

<< < (4/5) > >>

KodeZwerg:
A windows only solution that each folder can run 1 copy of your application can look like this:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program project1; {$mode objfpc}{$H+} uses  Windows, SysUtils, Base64,  {$IFDEF UNIX}  cthreads,  {$ENDIF}  {$IFDEF HASAMIGA}  athreads,  {$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, unit1  { you can add units after this }; {$R *.res} function GetNamedPipeServerProcessId(hNamedPipe: THandle;  out ServerProcessId: ULONG): BOOL; stdcall;  external kernel32 name 'GetNamedPipeServerProcessId'; function EnumWindowsProcCallback(HWnd: THandle; PID: LPARAM): BOOL; stdcall;var  WinPID: DWORD;begin  GetWindowThreadProcessId(HWnd, WinPID);  Result := WinPID <> (PULONG(PID))^;  if not Result then    SetForegroundWindow(HWnd); // Note: Windows forbid to use this, you need a different approach!end; const  FILE_FLAG_FIRST_PIPE_INSTANCE = $00080000;var  hPipeClient: THandle;  pipeName: AnsiString;  processID: ULONG;begin  pipeName := '\\.\pipe\' + Base64.EncodeStringBase64(ParamStr(0));  hPipeClient := CreateNamedPipe(PAnsiChar(pipeName),    PIPE_ACCESS_OUTBOUND or FILE_FLAG_FIRST_PIPE_INSTANCE,    PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT, 1, 4, 4, 0, nil);  if (hPipeClient <> INVALID_HANDLE_VALUE) then    begin       RequireDerivedFormResource := True;       Application.Scaled := True;       Application.Initialize;       Application.CreateForm(TForm1, Form1);       Application.Run;       CloseHandle(hPipeClient);    end  else    begin      hPipeClient := CreateFile(PAnsiChar(pipeName), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);       if hPipeClient <> INVALID_HANDLE_VALUE then       begin         if GetNamedPipeServerProcessId(hPipeClient, processID) then           EnumWindows(@EnumWindowsProcCallback, LPARAM(@processID));       end;       if (hPipeClient <> INVALID_HANDLE_VALUE) or (GetLastError <> ERROR_PIPE_BUSY) then         CloseHandle(hPipeClient);    end;end.

d7_2_laz:
So we've now three possible solutions to deal with this specific scenario too, wow!
Thank you for your contribution @Kodezwerg! I'd stay at the variation based on the link i pointed to (simply i've no problem with it), but this technique appears very interesting too (named pipes .. I wouldn't have thought of it here).

440bx:

--- Quote from: d7_2_laz on December 07, 2023, 03:45:21 pm ---My special use case is that my app might be placed in more than one folder, where each one is dedicated for a special working context / config / data.
Here i'd want to allow the app running concurrently when started from different folders,
but to prohibit each one to be started twice from a same folder.
When started again from the same folder, it simply would be brought to foreground.
When started from a different folder, that should be allowed.

--- End quote ---
Piece of cake. :)

The solution is to use the full image name (include path/directory) as the mutex name, note that you'll have to replace the backslash in the path since that character is not allowed in a mutex name (see Crea]"]>Blockedtex for details.)

That way, only instances that are started from the same directory will attempt to create the same mutex thus revealing there is already an instance running.   

Use GetCurrentProcess and GetProcessImageFilename to get the full name of your process which determines the name of the mutex that is (or will be) in use.

HTH.

d7_2_laz:
@440bx, … hm, to be understood as “this is another possibility, #4”
or:
 “take better this strategy, based on Mutexes, it’s better, because ..”?
And: would it be needed to be implemented newly, or does it, as modification, refer to an existing code pattern?

440bx:
The link you provided in a previous post and to which you referred to as your preferred option uses a mutex. 

Because of this, I consider what I suggested in my previous post simply a variation of that theme, one that accomplishes the additional requirements which the normal "use a mutex" does not accomplish, i.e, the normal mutex method does not allow multiple instances of the same program to run if they reside in different directories (because all instances normally use the same mutex name.)

You can consider the method I suggested option #4 if you'd like but, I see it more as option #3.1 <chuckle>

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version