我只想在我的AppleScript生命周期中记录对象的状态。在其他语言中,对象的toString()方法将呈现等效的文本,我可以使用它们。在AppleScript中,情况似乎并非如此。
convert applescript object to string (similar to toString)
将finder对象(及其属性)输出到AppleScript Editor的“结果”窗口,但前提是它是最后一个执行的语句。
如果我有一个trace()语句(它为记录目的而接收一条消息):
on trace(message)
do shell script "cat >>~/log/applescript.txt <<END_OF_THE_LOG
" & (message as text) & "
END_OF_THE_LOG"
end trace
并尝试记录同一个对象,我得到了
Can’t make properties of application "Finder" into type text.
我愿意更好地登录到控制台,但想知道如何在脚本中间编写对象的属性(如AppleScript编辑器),以便进行测试。
答案 0 :(得分:34)
AppleScript并不容易:
log
运行时 osascript
仅日志(在这种情况下为stderr
) - 输出将是在其他情况下丢失,例如当应用程序运行带有NSAppleScript
Cocoa类的脚本时。
log
只接受一个参数;虽然它确实接受任何对象类型,但它并不容易获得非内置类型的有意义表示:例如,尝试log me
来获取有关脚本本身的信息;通常,必须使用log (get properties of <someObj>)
来获取有意义的信息;请注意繁琐的语法,这是必需的,因为只使用log properties of <someObj>
通常只打印引用表单的名称而不是它指向的属性(例如,log properties of me
无用的输出只是(*properties*)
)。
通常,AppleScript很难获得非内置类型对象的有意义的文本表示:<someObj> as text
(与<someObj> as string
相同)恼人地 break < / em> - 抛出运行时错误 - 对于此类对象;试试me as text
。
以下是解决这些问题的辅助子程序:
dlog()
是一个子程序,它结合了任何对象的有意义的文本表示,并能够根据全局配置变量写入多个日志目标(包括syslog和文件)。 / LI>
toString()
(有效地嵌入dlog()
)是一个子程序,它接受任何类型的单个对象,并从中获取有意义的文本表示。对@ 1.61803的帽子提示;他的回答提供了实现各种日志目标的指示。
# 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"}
有关详细信息,请参阅每个子例程上方的源代码注释。
# 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
# 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
答案 1 :(得分:29)
只需在AppleScript编辑器中使用log
语句即可。在Applescript Editor中查看结果时,在窗口底部按“事件”按钮。通常按下“结果”按钮,然后您只能看到最后一个语句的结果。因此,将按钮更改为“事件”。这将显示脚本运行时发生的所有事情,以及您在整个代码中放置的所有log
语句。请注意,log
语句不必是文本。您可以记录任何对象。
这是调试脚本并查看正在发生的事情的最佳方法。举个例子,看看“事件”。如果您查看事件,实际上认为您不需要很多log
语句,因为所有内容都已记录!
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
答案 2 :(得分:10)
请尝试以下任何一项:
# 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
如果您尝试记录的内容不是文字,您可以尝试:
quoted form of (myObj as string)
答案 3 :(得分:1)
do shell script "echo '" & (current date) & ": Found " & Thisfilename & "' >> ~/logs/MyGreatAppleScript.log"
答案 4 :(得分:1)
与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
答案 5 :(得分:1)
以下是控制台日志的示例:
set my_int to 9945
log my_int
set my_srt to "Hamza"
log my_srt
set my_array ["Apple","Mango","Banana","Gava"]
log my_array
set my_obj to {"Ali"} as string
log my_obj
答案 6 :(得分:0)
了解价值观的最简单方法-
display dialog "my variable: " & myVariableName
答案 7 :(得分:0)
对于运行时间很长而且我不看屏幕的脚本,我喜欢让 applescript 大声说出它在做什么。
即
say “This is a log statement.”
如果在 tell 语句中:
tell me to say “This is a log statement.”