Using NSWorkspace with Applications

In a continuation of the Cocoa Snippets experiment, we're going to talk about the basics of NSWorkspace in several parts. First, we're going to look at how you can use this class to work with other applications.

You can use NSWorkspace to get a list of running applications. For example:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSArray * apps = [ws launchedApplications];
NSLog (@"%@", apps);


The output would look something like this:

{
  NSApplicationBundleIdentifier = "com.apple.finder";
  NSApplicationName = Finder;
  NSApplicationPath = "/System/Library/CoreServices/Finder.app";
  NSApplicationProcessIdentifier = 184;
  NSApplicationProcessSerialNumberHigh = 0;
  NSApplicationProcessSerialNumberLow = 1048577;
},
{
  NSApplicationBundleIdentifier = "com.macromates.textmate";
  NSApplicationName = TextMate;
  NSApplicationPath = "/Applications/TextMate.app";
  NSApplicationProcessIdentifier = 220;
  NSApplicationProcessSerialNumberHigh = 0;
  NSApplicationProcessSerialNumberLow = 2490369;
},
{
  NSApplicationBundleIdentifier = "com.apple.iTunes";
  NSApplicationName = iTunes;
  NSApplicationPath = "/Applications/iTunes.app";
  NSApplicationProcessIdentifier = 242;
  NSApplicationProcessSerialNumberHigh = 0;
  NSApplicationProcessSerialNumberLow = 3145729;
},


The bundle identifier is set in Info.plist, and is the unique string that Launch Services needs to manage the application in the system. The process indentifier is the unix pid number. This could be used, for example, with the 'kill' command in the shell.

We can simplify and clean up this output a bit using NSArray's implementation of KVC:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
BOOL result = [ws launchApplication:@"Safari"];
NSArray * apps;
apps = [ws valueForKeyPath:@"launchedApplications.NSApplicationName"];
NSLog (@"%@", apps);


Which results in this:

(
  Finder,
  TextMate,
  iTunes
)


We can also launch an application. The most simple way to do this is with -launchApplication:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
BOOL wasLaunched = [ws launchApplication:@"Safari"];
if ( wasLaunched )
  NSLog (@"Safari was launched");
else
  NSLog (@"Safari was not launched");
NSArray * apps;
apps = [ws valueForKeyPath:@"launchedApplications.NSApplicationName"];
NSLog (@"%@", apps);


Keep in mind, though, that Safari may not be actually up and running by the time you reach the next line, even if the result is "true":

MyApp[620] Safari was launched
MyApp[620] (
  Finder,
  TextMate,
  iTunes
)


You may want to launch an application but keep your app in the foreground. This can be done with by sending a more detailed launch message:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];

[ws launchAppWithBundleIdentifier: @"com.apple.Safari"
                          options: NSWorkspaceLaunchWithoutActivation
   additionalEventParamDescriptor: NULL
                 launchIdentifier: nil];


Finally, you might want to get an icon for an application. This is done in two steps:

NSWorkspace * ws    = [NSWorkspace sharedWorkspace];
NSString    * path  = [ws fullPathForApplication:@"Safari"];
NSImage     * icon  = [ws iconForFile: path];
NSLog (@"%@", icon);


This will give you something like the following:

NSImage 0x39b940 Size={32, 32} Reps=(
  NSBitmapImageRep 0x39d5e0 Size={128, 128} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=128x128 Alpha=YES Planar=NO Format=0,
  NSBitmapImageRep 0x39dd20 Size={32, 32} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=32x32 Alpha=YES Planar=NO Format=0,
  NSBitmapImageRep 0x39d740 Size={16, 16} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=16x16 Alpha=YES Planar=NO Format=0
)


... which is only moderately interesting. What you'd probably want to do to display the icon is to use NSImage's -compositeToPoint:operation: to draw into a view. Alternately, you could just use an NSImageView, and use -setImage:.

There's more ground to cover with NSWorkspace beyond just dealing with applications. We'll look at that next time.

Update

By request, here's how to open a particular URL in Safari:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSURL * url = [NSURL URLWithString:@"http://theocacao.com/"];
[ws openURL: url];
Design Element
Using NSWorkspace with Applications
Posted Oct 27, 2005 — 11 comments below




 

Chuck — Oct 27, 05 467

Scott,

Thank you for these Cocoa articles. I really enjoy them. Please continue.

-Chuck

David Weiss — Oct 28, 05 471

Scott, I really enjoy reading your articles on Cocoa. Please keep up the great work!

David Weiss

JB — Oct 28, 05 472

Thank you for these simple, yet insightful, snippets!

Dman — Oct 28, 05 475

Scott,

can you expand the example to show how one would launch Safari with a particular URL?

Cheers.

D.

Scott Stevenson — Oct 28, 05 476 Scotty the Leopard

Done.

Jussi — Oct 30, 05 483

Thanks for great snippets and great new design.

The last example does not actually open the URL in Safari, but in the "Default Web Browser"

George — Oct 31, 05 485

I love seeing these as well. Thanks!

Jorge — Sep 09, 06 1779

Is there a way to get the list of installed apps (apart from looking into the /Applications directory)?

Thanks!

Pir — Jun 23, 07 4437

I'm new to Cocoa. More used to C++. I need to find out the size and position of all open windows on the desktop. I thought that it should be something related to the topic above. But I can't find how to get the window information from an application... because then I could do something like the code above.

Scott Stevenson — Jun 23, 07 4438 Scotty the Leopard

I need to find out the size and position of all open windows on the desktop
I'm not sure how to do that or if it even exists as API. If it exists, it might be somewhere in the CoreGraphics reference. It's also possible that you might somehow be able to do this with the Acessibility API or even AppleScript.

This would also be a good question to ask on Apple's cocoa-dev mailing list.

Nathan Gray — Dec 04, 07 5169

Pir: Check out CGWindow.h. You'll need to search for it and it's only in Leopard. The accessibility API is also a possibility, but it's impossible to match reliably a window inside that API with one outside it.




 

Add Your Thoughts

Use UBB tags: [b] [i] [url] [code], and so on
Use [i] for quoting: [i]Quoted Text[/i]
Omit double quotes in links: [url=http://apple.com]Apple[/url]
Accented characters are currently stripped from names



Please enter the company who makes the Mac:
this is an anti-spam measure
Some comments may be edited for formatting, or removed if too far off-topic.




Technorati Profile
Copyright © Scott Stevenson 2004-2008