11

In order to store an object's values for external (outside AS) access, I need to be able to get every property of that object, and then I'd try to coerce it to text and store it somehwere.

How do I get the list of properties that an object holds. As an example, I can write this:

tell me
  get properties
end tell

That works for a script object.

But for many other objects, I simply get an error such as "descripter type mismatch", like here:

tell application "iTunes"
  get properties of file track 1
end tell

Now, I know the excellent Script Debugger can do it (it can show any object's entire set of properties), so it should be possible in written AppleScript as well. What's the secret to this?

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149

6 Answers6

9

Mark Alldritt, the author of Script Debugger, was so kind to explain the "secret" to me.

Script Debugger uses some special AppleScript API functions, including OSAGetPropertyNames(), to get to this information.

Hence, if I write a wrapper in, for instance, C, I can probably get to this, too.

Update

The Cocoa Scripting API has a dedicated classes for this (NSScriptSuiteRegistry and NSScriptClassDescription) - the framework builds this information from reading an app's scripting definition (.sdef) file. With that, all the available class and their properties can be learned quite easily.

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
5

Script Debugger is Applescript, just with a bunch of programming tools placed around it. But a "descriptor type mismatch" really shouldn't enter into it. Can you show your code, because this works just fine in Script Editor:

tell application "Finder"
    set theFile to choose file
    get properties of theFile -- the "return" keyword also works here as well
end tell

Different applications will behave different, but without example code, there are too many variations to say definitively.

Update per comment and updated question: Again, different applications behave differently. An application actually has to have a properties property in order to get a record returned to you (though sometimes this is different from other information that can be gained from an object). Typically, this is implemented at a root class—item in most cases; iTunes doesn't allow for this. Not even Script Debugger can get around that.

Philip Regan
  • 5,005
  • 2
  • 25
  • 39
  • Philip, do you have Script Debugger? Because it *does* show all properties! That's the whole point of my question. – Thomas Tempelmann Nov 23 '10 at 09:02
  • I use Script Debugger every day, but it did not show the properties in the return value area of the return window of the object when I used your example code. Unless you are able to get to the property values somewhere else that I don't know about, I'm pretty sure there needs to be a `properties` property in order to get a record with all the properties in one fell swoop. I could easily do it with the Finder, Adobe InDesign, and a couple other apps but not iTunes, and `properties` was the differential – Philip Regan Nov 23 '10 at 10:35
  • I meant this: When I do "get file track 1" on iTunes in SD, then it shows me the result's properties, i.e. all members of the retrieved track. I see this in the Results drawer, with the "Best" view mode and "Pretty Print". You surely have seen this before, haven't you? – Thomas Tempelmann Nov 24 '10 at 22:28
  • `get file track 1` and `get properties of file track 1` are two different commands entirely. Now I see it, but not with your original code. I don't have experience with scripting iTunes, only those applications that utilize a `properties` properties. – Philip Regan Nov 25 '10 at 00:47
4

There is a trick you can use, because you can force Applescript to tell you the error, and this text includes the properties of the object that was the target.

set myThing to {FirstName:"Fred", LastName:"Smith"}
ListProperties(myThing)
on ListProperties(MyObject)
try
    get properties of MyObject
on error errText number errNum
    set pStart to offset of "{" in errText
    set structure to text pStart thru ((length of errText) - 2) of errText
    set TIDL to AppleScript's text item delimiters
    set AppleScript's text item delimiters to ","
    set fields to text items of structure as list
    set myMessage to ""
    repeat with f from 1 to count of fields
        set AppleScript's text item delimiters to ":"
        set theseItems to text items of (item f of fields) as list
        set itemPropName to text 2 thru length of item 1 of theseItems
        set itemValue to item 2 of theseItems
        set myMessage to myMessage & "Property Label: " & itemPropName & tab & "Value: " & itemValue & linefeed
    end repeat
    set AppleScript's text item delimiters to TIDL
    display dialog myMessage
end try
end ListProperties
Cilan
  • 13,101
  • 3
  • 34
  • 51
Ian
  • 41
  • 1
  • 1
    Nice idea, but it doesn't work for my above test case (file track 1 of app "itunes") because the error message does not include the affected object props that your code seeks to look into then. – Thomas Tempelmann Nov 27 '12 at 16:34
  • I used a version of this for reminders, though note that date values have both "," and ":", so I had to grab the key, then join the remaining values on the delimiter. AND, I parsed out the types, like `container: list id "..."` and `date "January..."` by splitting on quotes and grapping the second value. – hepcat72 Jun 06 '21 at 14:07
4

The ability for an app to return a "properties" property has always existed, but it took considerable more work pre-Cocoa than after. Pre-Cocoa, the developer had to build an AEList structure populated with keys and values for each property, then return it in an typePropertyList descriptor. Many developers did not bother. With Cocoa Scripting, you basically get this for free AS LONG AS you use KVC-compliant names for all of the properties of your class AND you get the terminology and cocoa-keys in your SDEF file properly configured.

BTW, in 2016, iTunes 12.3.3,

tell application "iTunes" to get properties of file track 1

correctly returns a long list of properties.

Ron Reuter
  • 1,287
  • 1
  • 8
  • 14
  • Since I've been digging into Cocoa Scripting, I've found that there's even two classes that let me query the entire info from an Sdef file now, and it can also be used to read the sdefs of other apps and parse them. Those classes are `NSScriptSuiteRegistry` and `NSScriptClassDescription`. – Thomas Tempelmann Apr 04 '16 at 13:56
  • @ThomasTempelmann You said: _"I've found that there's even two classes that let me query the entire info from an Sdef file now, and it can also be used to read the sdefs of other apps and parse them."_ How does one use the `NSScriptSuiteRegistry` class to read/parse the SDEFs of other apps? – CJK May 01 '19 at 15:52
  • @CJK Have you had a look at their header files, yet? There's `loadSuiteWithDictionary:fromBundle:`, for instance. – Thomas Tempelmann May 02 '19 at 16:24
  • @CJK I have seen data in those objects but don't remember exactly how I acquired it. It may have been a property somewhere that pointed to these objects, and then I found all the info in there. Maybe turn this into its own question and I might look into my code and find some answers – Thomas Tempelmann May 02 '19 at 19:56
  • And remember, NSScriptSuiteRegistry and NSScriptClassDescription just parse the and sections of the SDEF, so they report what the developer **claims** to have implemented. It is easy for the SDEF and the implementation to get out of sync, so take it with a grain of salt. – Ron Reuter May 03 '19 at 18:32
1

Many words are said here, but the main thing is not said. Why properties might work for some objects but might not work for others?

So, whether a Cocoa application is scriptable or not, it responds to commands and properties from the Standard Suite. In the Standard Suite, the properties property is a property of the "item" class of the Standard Suite and is available for objects (items) of the following classes:

application, attribute run, character, word, paragraph, color, text, document, window

In addition to the objects listed above, some scripted applications have an additional properties property, which is a property of the "item" class of the Application's Suite. The availability of this property depends on the specific application. For example, the Music.app application, in addition to the objects listed above, allows you to request for the properties of the following objects:

Airplay device, artwork, encoder, EQ preset, playlist, source, track, visual.

Finder.app has additional properties property of "item" class of Finder items suite + properties property of "item" class of Windows classes suite.

That is, the answer is this: you can get in the script the properties of those objects that the application allows in the Standard and additional suites together.

Robert Kniazidis
  • 1,760
  • 1
  • 7
  • 8
0

https://i.stack.imgur.com/9FTz0.jpg
info for is "deprecated" but has some useful properties like alias and type identifier

rridall
  • 9
  • 1