Sending launch and quit Apple Events: Crazy Connection Errors
I need to be able to quit and re-launch other applications, and have been getting all kinds of weird behavior. Maybe if someone could explain this one little test case I've isolated, it would be a big help. The code below attempts to launch TextEdit, wait 5 seconds, quit TextEdit, wait 5 seconds, repeat forever. I get a launch, a quit, and a launch. But when it tries to quit for the second time, AESendMessage returns a -609 Connection Invalid error. I imagine this is because it is trying to connect to the application instance that it had quit the first time. Documention of AESendMessage implies that recent versions of AppleScript will automatically try and reconnect, and that there is no more option to set. How can I get it to forget the old connection and make a new one? Thanks, Jerry P.S. I'm having another issue too. Under some conditions, if I launch an application using the NSWorkspace method, it will quit (quietly, no crash) as soon as my application resumes normal activity. I'm saving that for another post, unless someone has an Aha!. I've also tried using NSAppleScript and Scripting Bridge but have had similar problems. #import Cocoa/Cocoa.h void LaunchAndSleep(NSString* bundleIdentifier, float seconds) { NSLog(@Launching) ; BOOL ok ; ok = [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:bundleIdentifier options:0 additionalEventParamDescriptor:nil launchIdentifier:NULL] ; NSLog(@Launch success = %d, ok) ; NSLog(@Sleep after launch) ; usleep(seconds * 1e6) ; } void QuitAndSleep(NSString* bundleIdentifier, float seconds) { NSLog(@Quitting) ; const char* identifier = [bundleIdentifier UTF8String] ; NSAppleEventDescriptor *as ; as = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplicationBundleID bytes:identifier length:strlen(identifier)]; NSAppleEventDescriptor *ae ; ae = [NSAppleEventDescriptor appleEventWithEventClass:kCoreEventClass eventID:kAEQuitApplication targetDescriptor:as returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; AppleEvent *quitApplicationAppleEventPtr = (AEDesc*)[ae aeDesc]; if (quitApplicationAppleEventPtr) { OSStatus err = AESendMessage(quitApplicationAppleEventPtr, NULL, kAENoReply, kAEDefaultTimeout) ; NSLog(@Quit err = %d, err) ; } NSLog(@Sleep after quit) ; usleep(seconds * 1e6) ; } int main (int argc, const char * argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSString* bundleIdentifier = @com.apple.TextEdit ; while (YES) { LaunchAndSleep(bundleIdentifier, 5) ; QuitAndSleep(bundleIdentifier, 5) ; } [pool release] ; } ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Sending launch and quit Apple Events: Crazy Connection Errors
On Jul 7, 2009, at 8:21 AM, Jerry Krinock wrote: I need to be able to quit and re-launch other applications, and have been getting all kinds of weird behavior. Maybe if someone could explain this one little test case I've isolated, it would be a big help. The code below attempts to launch TextEdit, wait 5 seconds, quit TextEdit, wait 5 seconds, repeat forever. I get a launch, a quit, and a launch. But when it tries to quit for the second time, AESendMessage returns a -609 Connection Invalid error. I imagine this is because it is trying to connect to the application instance that it had quit the first time. Documention of AESendMessage implies that recent versions of AppleScript will automatically try and reconnect, and that there is no more option to set. How can I get it to forget the old connection and make a new one? Thanks, Jerry I added similar functionality to one of my apps, and had problems using the bundle id as well. I switched to using the PSN (typeProcessSerialNumber) and that seems to work. You can use this to get the PSN: void PSNForBundleIdentifier( NSString *bundleIdentifier, ProcessSerialNumber *psn ) { OSStatus anErr = noErr; ProcessSerialNumber aNum = { kNoProcess, kNoProcess }; if ( psn == NULL ) return; while ( (anErr == noErr) ) { anErr = GetNextProcess( aNum ); if ( anErr == noErr ) { CFDictionaryRef procInfo = ProcessInformationCopyDictionary( aNum, kProcessDictionaryIncludeAllInformationMask ); if ( [[(NSDictionary *)procInfo objectForKey:(NSString *)kCFBundleIdentifierKey] isEqualToString:bundleIdentifier] ) { *psn = aNum; CFRelease( procInfo ); break; } CFRelease( procInfo ); } } } And then change your QuitAndSleep function to: void QuitAndSleep(NSString* bundleIdentifier, float seconds) { NSLog(@Quitting) ; NSAppleEventDescriptor *as ; ProcessSerialNumber aNum = { kNoProcess, kNoProcess } ; PSNForBundleIdentifier( bundleIdentifier, aNum ); as = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:aNum length:sizeof(aNum)]; NSAppleEventDescriptor *ae ; ae = [NSAppleEventDescriptor appleEventWithEventClass:kCoreEventClass eventID:kAEQuitApplication targetDescriptor:as returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; AppleEvent *quitApplicationAppleEventPtr = (AEDesc*)[ae aeDesc]; if (quitApplicationAppleEventPtr) { OSStatus err = AESendMessage(quitApplicationAppleEventPtr, NULL, kAENoReply, kAEDefaultTimeout) ; NSLog(@Quit err = %d, err) ; } NSLog(@Sleep after quit) ; usleep(seconds * 1e6) ; } -- Darkshadow (aka Michael Nickerson) http://www.nightproductions.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Sending launch and quit Apple Events: Crazy Connection Errors
Wow, Michael! I pasted in your code, rebuilt, and it worked perfectly. Thanks! Since you made my day be being such a trooper, I decided to file a bug. Maybe we'll get this fixed someday. Jerry Problem ID: 7037206 Apple Event built with Bundle ID Tries Connect to previously-quit Process, Fails Summary: If an application quits another application using an Apple Event that was built with a Bundle ID, then re-launches the other application, then tries to quit it again, the re-quit Apple Event message fails, apparently because it tries to connect to the process that had been previously quit. Steps to Reproduce: 1. Build a Cocoa Tool using the code in the attached file AEDisconnectDemo.m. This tool is designed to repeatedly launch and then quit TextEdit.app Quitting is done by creating a Quit Apple Event using the bundle identifier of TextEdit.app. A new Apple Event is created with each launch/quit cycle. 2. Run the demo. Expected Results: It should launch TextEdit, sleep 5, quit TextEdit, sleep 5, then repeat this forever Actual Results: The second time it tries to quit TextEdit, AEMessageSend() returns a -609 Invalid Connection error and the operation fails. Apparently, it's trying to connect to the TextEdit process instance that it quit the first time. Notes: In the code, if you then un-comment USE_PSN_INSTEAD_OF_BUNDLE_ID, rebuild, and re-run, it works as expected. (Thanks to Michael Nickerson!) ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com