The somewhat supported (but poorly documented) approach is to call lsregister and parse the output. The output does not have a documented or guaranteed format, however.
You run it this way for the commandline:
LSREGISTER="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
${LSREGISTER} -dump
(Yes, it's deeply buried and not in PATH.)
This dumps a ton of information. You just want services, which look like this:
--------------------------------------------------------------------------------
service id: FileMerge/Compare To Master (0x16f8)
menu: FileMerge/Compare To Master
port: FileMerge
message: diffVersusMasterService
timeout: -1
send types: "NSFilenamesPboardType"
The part you want is the "menu" tag:
$LSREGISTER -dump | grep ^menu: | cut -c 29-
Obviously you can parse this more directly in code, but the only way I know of that's even vaguely supported is to run lsregister.
OK, that's obnoxious. If you're willing to use private APIs, it's pretty straightforward. Define an interface for LSServiceRecord:
@interface LSServiceRecord
+ (id)enumerator;
- (NSString *)localizedMenuItemTitle;
@end
And then you can enumerate over them to get the menu titles:
id enumerator = [LSServiceRecord enumerator];
for (id item in enumerator) {
NSLog(@"%@", [item localizedMenuItemTitle]);
}
You might find the portName property helpful. It's the name of the application that registered the service. You might also find +[LSServiceRecord enumeratorForContentsOfPasteboard:] useful if you're trying to limit it to valid services.
If you want to explore more, I recommend Hopper, and looking in LaunchServices framework.