Newbie here. I'm trying to create a small listener for application launches, and I already have this:
// almon.m
#import <Cocoa/Cocoa.h>
#import <stdio.h>
#include <signal.h>
@interface almon: NSObject {}
-(id) init;
-(void) launchedApp: (NSNotification*) notification;
@end
@implementation almon
-(id) init {
NSNotificationCenter * notify
= [[NSWorkspace sharedWorkspace] notificationCenter];
[notify addObserver: self
selector: @selector(launchedApp:)
name: @"NSWorkspaceWillLaunchApplicationNotification"
object: nil
];
fprintf(stderr,"Listening...\n");
[[NSRunLoop currentRunLoop] run];
fprintf(stderr,"Stopping...\n");
return self;
}
-(void) launchedApp: (NSNotification*) notification {
NSDictionary *userInfo = [notification userInfo]; // read full application launch info
NSString* AppPID = [userInfo objectForKey:@"NSApplicationProcessIdentifier"]; // parse for AppPID
int killPID = [AppPID intValue]; // define integer from NSString
kill((killPID), SIGSTOP); // interrupt app launch
NSString* AppPath = [userInfo objectForKey:@"NSApplicationPath"]; // read application path
NSString* AppBundleID = [userInfo objectForKey:@"NSApplicationBundleIdentifier"]; // read BundleID
NSString* AppName = [userInfo objectForKey:@"NSApplicationName"]; // read AppName
NSLog(@":::%@:::%@:::%@:::%@", AppPID, AppPath, AppBundleID, AppName);
}
@end
int main( int argc, char ** argv) {
[[almon alloc] init];
return 0;
}
// build: gcc -Wall almon.m -o almon -lobjc -framework Cocoa
// run: ./almon
Note: when I build it, it will run fine, but if you do it with Xcode 10 on High Sierra, you will get ld
warnings, which you can ignore, however.
My question: Is there a way to also detect a launch of a background application, e.g. a menu bar application like Viscosity etc.? Apple says that
the system does not post [NSWorkspaceWillLaunchApplicationNotification] for background apps or for apps that have the
LSUIElement
key in theirInfo.plist
file. If you want to know when all apps (including background apps) are launched or terminated, use key-value observing to monitor the value returned by therunningApplications
method.
I would at least try to add support for background apps etc. to the listener, but I don't know how to go about it. Any ideas?
As the document suggests, you use Key-Value Observing to observe the runningApplications
property of the shared workspace object:
static const void *kMyKVOContext = (void*)&kMyKVOContext;
[[NSWorkspace sharedWorkspace] addObserver:self
forKeyPath:@"runningApplications"
options:NSKeyValueObservingOptionNew // maybe | NSKeyValueObservingOptionInitial
context:kMyKVOContext];
Then, you would implement the observation method (using Xcode's ready-made snippet):
- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
if (context != kMyKVOContext)
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if ([keyPath isEqualToString:@"runningApplications"])
{
<#code to be executed when runningApplications has changed#>
}
}
来源:https://stackoverflow.com/questions/52710089/macos-detect-all-application-launches-including-background-apps