Getting List of Running Applications in Firemonkey for Windows and OSX

A common need for programmers is to prevent running of the application more than once. For this purpose we mainly use mutex in Windows programming and close the application if an already active mutex is in memory. In Firemonkey applications this approach is not valid in OSX side as it is in Windows. So the first alternative way that comes to mind is to search for all running applications at start-up and close the application if it has got two (2) instances. So the question is how we will get the list of running applications? We will need this also for Windows as well as OSX, because doing the things using the same strategy for both Windows and OSX is a common pattern in Firemonkey.

As you can see in one of my earlier articles, I have started a  new class named TPlatformExtensions, to host these kind of extra utilities which will expand platform specific usage. So I will add a new function to this class to solve this specific platform related problem.

Getting the Running Applications list in OSX

On OSX api, NSWorkspace class is used to deal with issues about the workspace that the application is hosted. And this class has got two selectors (methods) that is related with the subject.

- (NSArray *)launchedApplications
- (NSArray *)runningApplications

Both functions can be used to get the list of running Applications, however the first one is a deprecated one. So the second one should be used to get rid of future problems about compatibility, bu this function is not fully supported in Delphi port. Because this functions returns an array of NSRunningApplication objects which originally we can get any information about the application instance. However, in Firemonkey port this class includes a very brief list of methods which we can only learn the processId of the application that wont mean anything for us to check the double instantiation. So I decided to use the deprecated function hoping that soon I will replace it with the second one  after a possible hot-fix enriching the NSRunningApplication interface.

To be able to use workspace instance methods first we should have got an instance of our workspace. So we will call the

+ (NSWorkspace *)sharedWorkspace

class method to get the shared workspace. The launchedApplications methods returns an NSArray object which includes the list of NSDictionary objects that each of them represents a bundle of information of each running application. So we should typecast the items in the list to NSDictionary and get the values of the keys we know. Possible keys that we can use to get information about the application are NSApplicationBundleIdentifier, NSApplicationPath and NSApplicationName. Here how we do all in Delphi side.

class procedure TPlatformExtensionsMac.GetRunningAplications(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;

Getting the Running Applications list in Windows (32bit and 64bit)

In windows though the standard api introduced in Windows.pas doesn’t provide a support for getting the list of running applications, Microsoft has got a support in kernel32.dll called tool help library and fortunately Delphi has got a port of this group of functions under the name Winapi.TlHelp32.pas. So we will use this library to get the list of running applications by searching the heap with given functions. Don’t be mistaken by the name. It is used both in 32 and 64 bit modes. Here you can see how it is also easy to get the running applications list in Windows.

class procedure TPlatformExtensionsWin.GetRunningAplications(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;

You can get the source code of the PlatformExtensions classes with the demo application from this SVN link. For non-programmers the compiled Win32, Win64, MacOSX (Thanks to Firemonkey) applications are also available to download.

2 thoughts on “Getting List of Running Applications in Firemonkey for Windows and OSX

  1. stlcours

    Hello, sir. I have a question: how to close the application of firemonkey in Mac when it is busy doing another thing…In windows, we can use Application.ProcessMessages; to do the system messages(if we don’t use multithread), but how do it in mac? Please help me, thanks very much!

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s