Jak logować obiekty do konsoli za pomocą AppleScript

Staram się rejestrować stan przedmiotów przez całe życie mojego applescriptu. W innych językach, metody ToString() obiektu sprawią, że tekst będzie równoważny i mogę z nich korzystać. W AppleScript wydaje się, że tak nie jest.

convert applescript object to string (similar to toString)

Wyświetli obiekt finder (i jego właściwości) w oknie" Results " edytora AppleScript, ale tylko wtedy, gdy jest to ostatnie polecenie, które zostanie wykonane.

Jeśli mam polecenie trace () (które pobiera komunikat do logowania "purposes"): {]}

on trace(message)
do shell script "cat >>~/log/applescript.txt <<END_OF_THE_LOG
" & (message as text) & "
END_OF_THE_LOG"
end trace

I spróbuj zalogować ten sam obiekt, otrzymuję

Can’t make properties of application "Finder" into type text.

Jestem otwarty na lepsze sposoby logowania do konsoli, ale chciałbym dowiedzieć się, jak napisać właściwości obiektu (tak jak robi to edytor AppleScript) w środku skryptu do testowania.

Author: umop, 2012-12-01

5 answers

Wystarczy użyć instrukcji log w edytorze AppleScript. Po wyświetleniu wyników w edytorze Applescript w dolnej części okna naciśnij przycisk "zdarzenia". Zwykle przycisk" Results " jest wciśnięty, a następnie widzisz tylko wynik ostatniej instrukcji, jak wspominasz. Więc zmień przycisk na "wydarzenia". To pokaże Ci wszystko, co dzieje się w trakcie działania skryptu, a także wszystkie log instrukcje, które umieścisz w kodzie. Zauważ, że wypowiedzi log nie musi być SMS-em. Możesz zarejestrować dowolny obiekt.

Jest to najlepszy sposób, aby debugować skrypt i zobaczyć, co się dzieje. Jako przykład spróbuj tego i spójrz na "wydarzenia". Realistycznie myślałem, że nie potrzebujesz dużo log wypowiedzi, jeśli wyświetlasz zdarzenia, ponieważ wszystko jest już zalogowane!

set someFolder to path to desktop
log someFolder

tell application "Finder"
    set someItem to first item of someFolder
    log someItem

    set itemProps to properties of someItem
    log itemProps
end tell
 26
Author: regulus6633,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-24 19:36:51

AppleScript nie ułatwia:

  • log tylko loguje się podczas pracy w edytorze AppleScript lub podczas pracy przez osascript (w tym przypadku do stderr) - wyjście zostanie utracone w innych przypadkach, np. gdy aplikacje uruchamiają skrypt z klasą NSAppleScript Cocoa.

  • log przyjmuje tylko jeden argument; chociaż akceptuje dowolny typ obiektu, nie ułatwia to uzyskania znaczącej reprezentacji typów nie wbudowanych: spróbuj log me, aby uzyskać należy zwrócić uwagę na kłopotliwą składnię, która jest wymagana, ponieważ samo użycie log properties of <someObj> zazwyczaj wypisuje nazwę formularza referencyjnego zamiast właściwości, na które wskazuje (np.log properties of me wyświetla tylko (*properties*)).

  • Ogólnie Rzecz Biorąc, AppleScript sprawia, że bardzo trudno jest uzyskać znaczące reprezentacje tekstowe obiektów nie wbudowanych typów: <someObj> as text (tak samo jak: <someObj> as string) breaks - wyrzuca błąd runtime-dla takich obiektów; spróbuj me as text.

Poniżej znajdują się podprogramy pomocnicze, które rozwiązują te problemy :

  • dlog() jest podprogramem, który łączy w sobie znaczące reprezentacje tekstowe dowolnych obiektów z możliwością zapisu do wielu celów dziennika (w tym syslog i plików) w oparciu o globalną zmienną konfiguracyjną.
  • toString() (skutecznie osadzony w dlog()) jest podprogram, który pobiera pojedynczy obiekt dowolnego typu i wyprowadza z niego znaczącą reprezentację tekstową.

Wskazówka kapelusza do @1.61803; jego odpowiedź dostarczyła wskazówek do realizacji różnych celów logowania.

Przykłady:

  # Setup: Log to syslog and a file in the home dir.
  #        Other targets supported: "log", "alert"
  #        Set to {} to suppress logging.
set DLOG_TARGETS to { "syslog", "~/as.log" } 
  # Log properties of the front window of frontmost application.
dlog(front window of application (path to frontmost application as text))
  # Log properties of own front window; note the *list* syntax for multiple args.
dlog({"my front window: ", front window})

  # Get properties of the running script as string.
toString(me) # ->, e.g.: [script name="sandbox"] {selection:insertion point after character 2475 of text of document "sandbox2.scpt", frontmost:true, class:application, name:"AppleScript Editor", version:"2.6"}

Zobacz komentarze kodu źródłowego nad każdym podprogramem po szczegóły.


Dlog () kod źródłowy

    # Logs a text representation of the specified object or objects, which may be of any type, typically for debugging.
    # Works hard to find a meaningful text representation of each object.
    # SYNOPSIS
    #   dlog(anyObjOrListOfObjects)
    # USE EXAMPLES
    #   dlog("before")  # single object
    #     dlog({ "front window: ", front window }) # list of objects
    # SETUP
    #   At the top of your script, define global variable DLOG_TARGETS and set it to a *list* of targets (even if you only have 1 target).
    #     set DLOG_TARGETS to {} # must be a list with any combination of: "log", "syslog", "alert", <posixFilePath>
    #   An *empty* list means that logging should be *disabled*.
    #   If you specify a POSIX file path, the file will be *appended* to; variable references in the path
    #   are allowed, and as a courtesy the path may start with "~" to refer to your home dir.
    #   Caveat: while you can *remove* the variable definition to disable logging, you'll take an additional performance hit.
    # SETUP EXAMPLES
    #    For instance, to use both AppleScript's log command *and* display a GUI alert, use:
    #       set DLOG_TARGETS to { "log", "alert" }
    # Note: 
    #   - Since the subroutine is still called even when DLOG_TARGETS is an empty list, 
    #     you pay a performancy penalty for leaving dlog() calls in your code.
    #   - Unlike with the built-in log() method, you MUST use parentheses around the parameter.
    #   - To specify more than one object, pass a *list*. Note that while you could try to synthesize a single
    #     output string by concatenation yourself, you'd lose the benefit of this subroutine's ability to derive
    #     readable text representations even of objects that can't simply be converted with `as text`.
    on dlog(anyObjOrListOfObjects)
        global DLOG_TARGETS
        try
            if length of DLOG_TARGETS is 0 then return
        on error
            return
        end try
        # The following tries hard to derive a readable representation from the input object(s).
        if class of anyObjOrListOfObjects is not list then set anyObjOrListOfObjects to {anyObjOrListOfObjects}
        local lst, i, txt, errMsg, orgTids, oName, oId, prefix, logTarget, txtCombined, prefixTime, prefixDateTime
        set lst to {}
        repeat with anyObj in anyObjOrListOfObjects
            set txt to ""
            repeat with i from 1 to 2
                try
                    if i is 1 then
                        if class of anyObj is list then
                            set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}} # '
                            set txt to ("{" & anyObj as string) & "}"
                            set AppleScript's text item delimiters to orgTids # '
                        else
                            set txt to anyObj as string
                        end if
                    else
                        set txt to properties of anyObj as string
                    end if
                on error errMsg
                    # Trick for records and record-*like* objects:
                    # We exploit the fact that the error message contains the desired string representation of the record, so we extract it from there. This (still) works as of AS 2.3 (OS X 10.9).
                    try
                        set txt to do shell script "egrep -o '\\{.*\\}' <<< " & quoted form of errMsg
                    end try
                end try
                if txt is not "" then exit repeat
            end repeat
            set prefix to ""
            if class of anyObj is not in {text, integer, real, boolean, date, list, record} and anyObj is not missing value then
                set prefix to "[" & class of anyObj
                set oName to ""
                set oId to ""
                try
                    set oName to name of anyObj
                    if oName is not missing value then set prefix to prefix & " name=\"" & oName & "\""
                end try
                try
                    set oId to id of anyObj
                    if oId is not missing value then set prefix to prefix & " id=" & oId
                end try
                set prefix to prefix & "] "
                set txt to prefix & txt
            end if
            set lst to lst & txt
        end repeat
        set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {" "}} # '
        set txtCombined to lst as string
        set prefixTime to "[" & time string of (current date) & "] "
        set prefixDateTime to "[" & short date string of (current date) & " " & text 2 thru -1 of prefixTime
        set AppleScript's text item delimiters to orgTids # '
        # Log the result to every target specified.
        repeat with logTarget in DLOG_TARGETS
            if contents of logTarget is "log" then
                log prefixTime & txtCombined
            else if contents of logTarget is "alert" then
                display alert prefixTime & txtCombined
            else if contents of logTarget is "syslog" then
                do shell script "logger -t " & quoted form of ("AS: " & (name of me)) & " " & quoted form of txtCombined
            else # assumed to be a POSIX file path to *append* to.
                set fpath to contents of logTarget
                if fpath starts with "~/" then set fpath to "$HOME/" & text 3 thru -1 of fpath
                do shell script "printf '%s\\n' " & quoted form of (prefixDateTime & txtCombined) & " >> \"" & fpath & "\""
            end if
        end repeat
    end dlog

ToString() kod źródłowy

    # Converts the specified object - which may be of any type - into a string representation for logging/debugging.
    # Tries hard to find a readable representation - sadly, simple conversion with `as text` mostly doesn't work with non-primitive types.
    # An attempt is made to list the properties of non-primitive types (does not always work), and the result is prefixed with the type (class) name
    # and, if present, the object's name and ID.
    # EXAMPLE
    #       toString(path to desktop)  # -> "[alias] Macintosh HD:Users:mklement:Desktop:"
    # To test this subroutine and see the various representations, use the following:
    #   repeat with elem in {42, 3.14, "two", true, (current date), {"one", "two", "three"}, {one:1, two:"deux", three:false}, missing value, me,  path to desktop, front window of application (path to frontmost application as text)}
    #       log my toString(contents of elem)
    #   end repeat
    on toString(anyObj)
        local i, txt, errMsg, orgTids, oName, oId, prefix
        set txt to ""
        repeat with i from 1 to 2
            try
                if i is 1 then
                    if class of anyObj is list then
                        set {orgTids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {", "}}
                        set txt to ("{" & anyObj as string) & "}"
                        set AppleScript's text item delimiters to orgTids # '
                    else
                        set txt to anyObj as string
                    end if
                else
                    set txt to properties of anyObj as string
                end if
            on error errMsg
                # Trick for records and record-*like* objects:
                # We exploit the fact that the error message contains the desired string representation of the record, so we extract it from there. This (still) works as of AS 2.3 (OS X 10.9).
                try
                    set txt to do shell script "egrep -o '\\{.*\\}' <<< " & quoted form of errMsg
                end try
            end try
            if txt is not "" then exit repeat
        end repeat
        set prefix to ""
        if class of anyObj is not in {text, integer, real, boolean, date, list, record} and anyObj is not missing value then
            set prefix to "[" & class of anyObj
            set oName to ""
            set oId to ""
            try
                set oName to name of anyObj
                if oName is not missing value then set prefix to prefix & " name=\"" & oName & "\""
            end try
            try
                set oId to id of anyObj
                if oId is not missing value then set prefix to prefix & " id=" & oId
            end try
            set prefix to prefix & "] "
        end if
        return prefix & txt
    end toString
 29
Author: mklement0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 13:04:12

Spróbuj jednego z następujących:

# echo to file
do shell script "echo " & quoted form of (myObj as string) & ¬
    " > ~/Desktop/as_debug.txt"

# write to file
set myFile to open for access (path to desktop as text) & ¬
    "as_debug2.txt" with write permission
write myObj to myFile
close access myFile

# log to syslog
do shell script "logger -t 'AS DEBUG' " & myObj

# show dialog
display dialog "ERROR: " & myObj

Jeśli to, co próbujesz zalogować, nie jest tekstem, możesz spróbować:

quoted form of (myObj as string)
 9
Author: 1.61803,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-20 14:03:20
do shell script "echo '" & (current date) & ": Found " & Thisfilename & "' >> ~/logs/MyGreatAppleScript.log"
 1
Author: user2548919,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-28 17:31:54

Podobne do toString()...

on TextOf(aVariable)
    try
        return "" & aVariable
    on error errm
        if errm begins with "Can’t make " ¬
       and errm ends with " into type Unicode text." then ¬
            return text 12 through -25 of errm
        return "item of class " & (class of aVariable) & return & errm
    end try
end TextOf
 0
Author: Gil Dawson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 00:26:33