2

With FireMonkey and a multi-platform application (Windows + Mac OS X), how to have only one instance of an application running at the same time?

If a previous instance is already running, how to set it as the desktop foreground window?

  • I can check if a file is locked:
    • not locked: I lock it and run normally
    • locked : find the previous version (on windows, I know how to.. but on mac ?) and set it as the foreground window
  • I can check how many times the same process is launched (ditto, on windows, ok, but how to do it on Mac OS X)
  • ...
Whiler
  • 7,998
  • 4
  • 32
  • 56

1 Answers1

5

Both for Windows and OSX you can get the list of running applications and check if yours is in the list before you close with a message. In OSX you can get the list with lauchedApplications method of NSWorkspace, and in Windows you can use the toolhelp32 library for same purpose. Here are the related codes from TPlatformExtensions class which I have blogged in my website.

For OSX:

uses Macapi.AppKit, Macapi.Foundation;

class procedure TPlatformExtensionsMac.GetRunningApplications(
  Applist: TStringlist);
var
  fWorkSpace:NSWorkSpace;
  list:NSArray;
  i: Integer;
  lItem:NSDictionary;
  key,value: NSString;
begin
  fWorkSpace := TNsWorkspace.Wrap(TNsWorkSpace.OCClass.sharedWorkspace);
  list := fWorkspace.launchedApplications;
  if (List <> nil) and (List.count > 0) then
  begin
    for i := 0 to list.count-1 do
    begin
      lItem := TNSDictionary.Wrap(List.objectAtIndex(i));
      key := NSSTR(String(PAnsiChar(UTF8Encode('NSApplicationBundleIdentifier'))));
      // You can also use NSApplicationPath or NSApplicationName
      value := TNSString.Wrap(lItem.valueForKey(key));
      Applist.Add(String(value.UTF8String));
    end;
  end;
end; 

For Windows:

uses Winapi.TlHelp32, Winapi.Windows;

class procedure TPlatformExtensionsWin.GetRunningApplications(
  Applist: TStringlist);
var
 PE: TProcessEntry32;
 Snap: THandle;
 fName: String;
begin
  pe.dwsize:=sizeof(PE);
  Snap:= CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Snap <> 0 then
  begin
    if Process32First(Snap, PE) then
    begin
     fName := String(PE.szExeFile);
     Applist.Add(fName);
     while Process32Next(Snap, PE) do
     begin
       fName := String(PE.szExeFile);
       Applist.Add(fName);
     end;
    end;
    CloseHandle(Snap);
  end;
end; 

If you need further information about the subject you can read my article on the subject.

Whiler
  • 7,998
  • 4
  • 32
  • 56
mehmed.ali
  • 252
  • 1
  • 4