Sending launch and quit Apple Events: Crazy Connection Errors

2009-07-07 Thread Jerry Krinock
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

2009-07-07 Thread Michael Nickerson


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

2009-07-07 Thread Jerry Krinock
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