Quinn <mailto:eskimo1@apple.com> wrote (Tuesday, January 29, 2008 3:45 AM -0000):
A better solution is to look at the kAEWhyAmIBeingLoggedOutAttr ('why?') attribute of the kAEQuitApplication ('quit') Apple event. If you're being quit by loginwindow, this will contain one of four different codes indicating why (kAEQuitAll, kAEShutDown, kAERestart, kAEReallyLogOut). If you're being quit by the user (or by an AppleScript or any other 'quit' Apple event mechanism), this attribute won't be present.
Thanks, Quinn. That's a excellent solution. I did, indeed, search the documentation, developer.apple.com, and the various lists for any mention of determining if a Quit event was being sent because of a shutdown, restart, or logout. So this isn't just undocumented, it's below the radar. Inside Apple, you're probably using header files we don't have. ;) grepping of all of the 10.4 & 10.5 SDK header files, I can't find any declaration for kAEWhyAmIBeingLoggedOutAttr. However, there is a declaration for kEventParamReason = 'why?' in CarbonEvents.h. That's good enough for me. So I think I have this working nicely now. I added the SuccessfulExit=false to the KeepAlive property and added the following code to my Cocoa application static void dirtyExit( void ) { // At the very last moment possible, force an abnormal exit _exit(2); } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender { #pragma unused(sender) // Find out if the application is quitting for a Log Out, Shutdown, or Restart // This has to be detemined in applicationShouldTerminate: becuase the AppleEvent goes away soon. NSAppleEventDescriptor* quitEventDesc = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent]; // NSLog(@"%p%s %@",self,__func__,quitEventDesc); NSAppleEventDescriptor* whyDesc = [quitEventDesc attributeDescriptorForKeyword:kEventParamReason]; OSType why = [whyDesc typeCodeValue]; if ( !(why==kAEQuitAll || why==kAEShutDown || why==kAERestart || why==kAEReallyLogOut) ) { //NSLog(@"application will exit abnormally"); // If the monitor is not exiting cleanly, register a program exit handler that will throw an error following normal termination atexit(dirtyExit); } return (YES); } Thanks again. I'll file a bug report on the documentation. James -- James Bucanek