• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Using AppleEvents with the Finder in Sys 7

Mike68k

Member
Hi all,
I've been developing an app for these old Macs called MacDock (on GitHub, feel free to fork or contribute or comment!) - It's like the Dock in modern Macs but for 68k.

It's been great but I'm trying to add features like on modern macOS where you Cmd+click on an app and it will show the app in the Finder. I'm trying to use the AppleEvents from the Finder to make this happen but I'm having trouble getting what I think is the best apple event to do this to work.

Here's a screenshot from Resourcerer which I was using to try to find and learn the syntax of the best one:
1683952765420.png

But I can't seem to get the syntax right in my C code. I got it to the point where when I try it, it will switch to Finder but I just get a complaint message from the finder saying it couldn't find the item.

//Note for anyone on TinkerDifferent, yes I'm the same guy over there who got hung up and was pointed in the direction of 68kMLA for deeper expertise.
Here's that thread if interested (see pg 4).


If anyone has any resources or old books that explain the syntax for this Finder AppleEvent, I'd really appreciate it. I'll stop here, short of posting code. But if you're inclined here's the direct link to a post where I shared the code.
 

cheesestraws

Well-known member
Could you lift out that code from your application to provide a minimal test case that fails? Just an application that tries to send the apple event to highlight a specific application which fails. It'll make debugging easier for those of us who aren't used to your codebase :)
 

Phipli

Well-known member
What version of the Finder are you using? The Scriptable Finder was only added with Finder version 7.1.3 (with System 7 Pro). That finder can be used with System 7.1 to add Finder Scripting.

Sorry if you've indirectly explained already.
 

Mike68k

Member
What version of the Finder are you using? The Scriptable Finder was only added with Finder version 7.1.3 (with System 7 Pro). That finder can be used with System 7.1 to add Finder Scripting.

Sorry if you've indirectly explained already.
Using 7.5.5 but thanks for that info!! I had no idea.
 

Mike68k

Member
Could you lift out that code from your application to provide a minimal test case that fails? Just an application that tries to send the apple event to highlight a specific application which fails. It'll make debugging easier for those of us who aren't used to your codebase :)
I wish I could minimize it further but this is as simple as I know to make code that creates + sets up an appleEvent and its parameters and sends the event. I added comments to show what each line is (supposed to be) doing.

The one part I couldn't simply further was where I use ```gFSSpec_arr[1]``` as this is a global var of FSSpec records and I use it in the line where I setup my alias. In my last code post I included lines of code where I check the resulting myAlias and confirm that its contents make sense so *hopeully* this isn't likely to be the source of the problem... but so Murphy's law applies...


C:
void OpenAppDemo(){
    AEDesc aeDesc = {typeNull, NULL};
    AEDesc aliasDesc = {typeNull, NULL};
    long appSig, aliasKW;
    AppleEvent appleEvent, reply;
    
    AliasHandle myAlias; //alias pointing to some app
    AEDescList myList;
    
    appSig = 'MACS'; //Finder's app signature
    //Next line creates a descriptor with the app signature of Finder:
    AECreateDesc(typeApplSignature, (Ptr)(&appSig),
                (Size)sizeof(appSig), &aeDesc);
                
    //Create an AppleEvent directed at the Finder, where 'sope' is the Open keyword
    AECreateAppleEvent('FNDR', 'sope',
                            &aeDesc,
                            kAutoGenerateReturnID, 1L,
                            &appleEvent);
                            
    //Create a list of descriptors for the apple event parameters:
    AECreateList(nil, 0, false, &myList);
    
    //Make an alias pointing to some known app:
    NewAlias(nil,&(gFSSpec_arr[1]), &myAlias);   
    //Create an Alias Descriptor using myAlias:
    AECreateDesc(typeAlias, (Ptr)(&myAlias), (Size)sizeof(myAlias), &aliasDesc);
    
    //Add the alias descriptor to myList:
    AEPutDesc(&myList, 1, &aliasDesc);

    //Add the list as the parameter for appleEvent:
    AEPutParamDesc(&appleEvent,'fsel',(&myList));
    
    //Send the AppleEvent
    AESend( &appleEvent, &reply,
                kAENoReply+kAECanInteract+kAECanSwitchLayer,
                kAENormalPriority,
                kAEDefaultTimeout,
                nil, nil);
                
    //Dispose descriptors
    AEDisposeDesc(&aeDesc);
    AEDisposeDesc(&aliasDesc);
}

Let me know if you need any clarification on any of the above.

Moreover Inside Macintosh keeps making references to some document called
Apple Event Registry: Standard Suites. I do not know where I can find this document!

As always thanks for reading and more thanks if you respond.
 

cheesestraws

Well-known member
I added comments to show what each line is (supposed to be) doing.

Thanks!

Here are some thoughts:

You probably, at a guess, don't want to use the Open event: that will open the thing you're passing to it, as if the user double-clicked on it. If you want to reveal something in the Finder, you probably want to use the Reveal event. This takes an object and shows it in the Finder. Very convenient.

However, this is only available in the Scriptable Finder. So you will need to gate this function on the availability of the scriptable finder, which you can hoik out of the Gestalt Manager. The 7.0/7.1 Finder can get a bit funny about AppleEvents it doesn't understand, and you shouldn't fire them at it indiscriminately.

The Reveal event is called 'mvis', is in the 'misc' suite and takes a direct object that identifies the object to reveal. You don't need to construct an alias here, and indeed I couldn't get it to work with an alias. Instead, just pass in a FSSpec as the direct object.

Here is a hacked version of your code above that will reveal the System file in the System folder on a disk called untitled. You can, of course, pass in a different fsspec, rather than the hardcoded one I've used here. Please disregard the stdio guff, that was obviously for testing :).

C:
void OpenAppDemo(){
    AEDesc aeDesc = { 0 };
    AEDesc specDesc = { 0 };
    long appSig;
    AppleEvent appleEvent, reply;
    FSSpec fssp;
    OSErr err;
    
    err = FSMakeFSSpec(0, 0, "\puntitled:System Folder:System", &fssp);
    if (err != 0) {
        printf("makefsspec err: %d\n", (int)err);
    }
    
    appSig = 'MACS'; //Finder's app signature
    //Next line creates a descriptor with the app signature of Finder:
    AECreateDesc(typeApplSignature, (Ptr)(&appSig),
                (Size)sizeof(appSig), &aeDesc);
                
    //Create an AppleEvent directed at the Finder, where 'sope' is the Open keyword
    AECreateAppleEvent('misc', 'mvis',
                            &aeDesc,
                            kAutoGenerateReturnID, 1L,
                            &appleEvent);
    //Create an Alias Descriptor using myAlias:
    AECreateDesc(typeFSS, (Ptr)(&fssp), (Size)sizeof(FSSpec), &specDesc);
    AEPutParamDesc(&appleEvent, keyDirectObject, &specDesc);
    
    //Send the AppleEvent
    err = AESend( &appleEvent, &reply,
                kAENoReply+kAECanInteract+kAECanSwitchLayer,
                kAENormalPriority,
                kAEDefaultTimeout,
                nil, nil);
          
    if (err != 0) {
        printf("AESend: %d\n", (int)err);
    }
                
    //Dispose descriptors
    AEDisposeDesc(&aeDesc);
    AEDisposeDesc(&specDesc);
}

A reason you might not have spotted this event in the first place is that it's not in the Finder's 'aete' under 7.5.x: it's instead in the Finder Scripting Extension in the Extensions folder. The new interface and the code to implement it is defined in there.

Hope this helps!
 

Mike68k

Member
Thanks!

Here are some thoughts:

You probably, at a guess, don't want to use the Open event: that will open the thing you're passing to it, as if the user double-clicked on it. If you want to reveal something in the Finder, you probably want to use the Reveal event. This takes an object and shows it in the Finder. Very convenient.

However, this is only available in the Scriptable Finder. So you will need to gate this function on the availability of the scriptable finder, which you can hoik out of the Gestalt Manager. The 7.0/7.1 Finder can get a bit funny about AppleEvents it doesn't understand, and you shouldn't fire them at it indiscriminately.

The Reveal event is called 'mvis', is in the 'misc' suite and takes a direct object that identifies the object to reveal. You don't need to construct an alias here, and indeed I couldn't get it to work with an alias. Instead, just pass in a FSSpec as the direct object.

Here is a hacked version of your code above that will reveal the System file in the System folder on a disk called untitled. You can, of course, pass in a different fsspec, rather than the hardcoded one I've used here. Please disregard the stdio guff, that was obviously for testing :).

C:
void OpenAppDemo(){
    AEDesc aeDesc = { 0 };
    AEDesc specDesc = { 0 };
    long appSig;
    AppleEvent appleEvent, reply;
    FSSpec fssp;
    OSErr err;
   
    err = FSMakeFSSpec(0, 0, "\puntitled:System Folder:System", &fssp);
    if (err != 0) {
        printf("makefsspec err: %d\n", (int)err);
    }
   
    appSig = 'MACS'; //Finder's app signature
    //Next line creates a descriptor with the app signature of Finder:
    AECreateDesc(typeApplSignature, (Ptr)(&appSig),
                (Size)sizeof(appSig), &aeDesc);
               
    //Create an AppleEvent directed at the Finder, where 'sope' is the Open keyword
    AECreateAppleEvent('misc', 'mvis',
                            &aeDesc,
                            kAutoGenerateReturnID, 1L,
                            &appleEvent);
    //Create an Alias Descriptor using myAlias:
    AECreateDesc(typeFSS, (Ptr)(&fssp), (Size)sizeof(FSSpec), &specDesc);
    AEPutParamDesc(&appleEvent, keyDirectObject, &specDesc);
   
    //Send the AppleEvent
    err = AESend( &appleEvent, &reply,
                kAENoReply+kAECanInteract+kAECanSwitchLayer,
                kAENormalPriority,
                kAEDefaultTimeout,
                nil, nil);
         
    if (err != 0) {
        printf("AESend: %d\n", (int)err);
    }
               
    //Dispose descriptors
    AEDisposeDesc(&aeDesc);
    AEDisposeDesc(&specDesc);
}

A reason you might not have spotted this event in the first place is that it's not in the Finder's 'aete' under 7.5.x: it's instead in the Finder Scripting Extension in the Extensions folder. The new interface and the code to implement it is defined in there.

Hope this helps!
Oh man -- this info was great. I had no idea there was an extension (Finder Scripting Extension) that housed so many of the scripting calls. I've been looking everywhere for something like this.

I got it to work with my setup - thanks so much for the code and the time.


I have to ask --as my dream is to make this all work in System 6 as well -- any idea how this would be done in a world without AppleScript etc?? Would it be some weird low-level stuff?

THANK YOU!! (app update forthcoming when I can refine and test and deploy)
 

cheesestraws

Well-known member
Oh man -- this info was great. I had no idea there was an extension (Finder Scripting Extension) that housed so many of the scripting calls. I've been looking everywhere for something like this.

I also found the Finder Scripting column in develop magazine issue 20, and especially the sample code on the CD, useful when trying to work out why this wasn't working :).

I got it to work with my setup - thanks so much for the code and the time.

You're very welcome, glad it works!

I have to ask --as my dream is to make this all work in System 6 as well -- any idea how this would be done in a world without AppleScript etc?? Would it be some weird low-level stuff?

Yes: at that point you'd be doing horrible things to the inside of the Finder without permission. Is it possible? Quite possibly. Is it going to be fragile and crash-prone? Also quite possibly. It's a whole new level of deep magic compared to this, certainly.
 

Phipli

Well-known member
Yes: at that point you'd be doing horrible things to the inside of the Finder without permission. Is it possible? Quite possibly. Is it going to be fragile and crash-prone? Also quite possibly. It's a whole new level of deep magic compared to this, certainly.
There were hooks for doing the training macros from when they did the testing monkey thing wasn't there...

But yeah, there would be a lot of code around it working out what was needed.
 

Mike68k

Member
^^^there she is at work on my se/30. So slick!! Million thanks to all who supported on this. Many of whom were on the tinkerdifferent thread but a shout out to cheesestraws here for the clincher.

Ill read up on the Develop Magazine issue 20. I think ive seen it and its cds archived at one of the usual sites (internet archive i believe).

Ill test and polish and post to my git!
 

Crutch

Well-known member
@Mike68k when I mentioned to you before that there were some experts here on 68kmla who probalby know more about AppleEvents than me, @cheesestraws was the primary person I had in mind 🥳 So glad this worked out!
 
Top