Getting NSRunningApplication using a ProcessSerialNumber
Asked Answered
H

2

8

I have an AppleEventDescriptor where I need to get the sending application's bundle identifier. The Apple Event contains a typeProcessSerialNumber that can be coerced into a ProcessSerialNumber.

The problem is that GetProcessPID() was deprecated in 10.9, and there doesn't appear to be sanctioned way to get a pid_t that can be used to instantiate a NSRunningApplication using -runningApplicationWithProcessIdentifier:.

All the other options I've found all live in Processes.h and are also deprecated.

Am I missing something or do I have to live with this deprecation warning?

Hereafter answered 24/6, 2014 at 19:31 Comment(0)
H
8

Both Brian and Daniel provided great clues that helped me find the right answer, but the stuff they suggested was just a bit off. Here's how I ended up solving the problem.

Brian was correct about the code to get an Apple Event descriptor for a process id instead of the one for the serial number:

// get the process id for the application that sent the current Apple Event
NSAppleEventDescriptor *appleEventDescriptor = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
NSAppleEventDescriptor* processSerialDescriptor = [appleEventDescriptor attributeDescriptorForKeyword:keyAddressAttr];
NSAppleEventDescriptor* pidDescriptor = [processSerialDescriptor coerceToDescriptorType:typeKernelProcessID];

The problem is that if you take the -int32Value from that descriptor, a value of 0 is returned (i.e. no process id.) I have no idea why this happens: in theory, both pid_t andSInt32 are signed integers.

Instead, you need to get the byte values (which are stored little endian) and cast them into a process id:

pid_t pid = *(pid_t *)[[pidDescriptor data] bytes];

From that point, it's straightforward to get the information about the running process:

NSRunningApplication *runningApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
NSString *bundleIdentifer = [runningApplication bundleIdentifier];

Also, Daniel's suggestion of using keySenderPIDAttr won't work in many cases. In our new sandboxed world, the value stored there is likely to be the process id for /usr/libexec/lsboxd, also known as the Launch Services sandbox daemon, not the process id of the app that originated the event.

Thanks again to Brian and Daniel for the help that led to this solution!

Hereafter answered 24/6, 2014 at 23:50 Comment(0)
C
3

You can use Apple event descriptor coercion to translate the ProcessSerialNumber descriptor into a pid_t descriptor like so:

NSAppleEventDescriptor* processSerialDescriptor = [myEvent attributeDescriptorForKeyword:keyAddressAttr];
NSAppleEventDescriptor* pidDescriptor = [processSerialDescriptor coerceToDescriptorType:typeKernelProcessID];
pid_t pid = [pidDescriptor int32Value];
Cynarra answered 24/6, 2014 at 19:48 Comment(1)
Alternatively you can use the keySenderPIDAttr to get right at the PID without looking up the sender and coercing it: [[event attributeDescriptorForKeyword:keySenderPIDAttr] int32Value]Realpolitik

© 2022 - 2024 — McMap. All rights reserved.