MacScript 无效的过程调用或参数
MacScript Invalid procedure call or argument
In OSX Excel 通过 MacScript
关键字为 运行 Applescript 代码提供功能。我正在 运行ning shell 通过此功能编写代码,它通常如下所示:
MacScript "do shell script ""/usr/bin/whatever"""
最近我决定要捕获输出(和 stderr),因为命令失败了,我想看看错误是什么……所以我这样重写了它:
MacScript "do shell script ""/usr/bin/whatever > /tmp/out 2>&1"""
但是我得到上面的错误。如果我 运行 在 AppleScript 编辑器中给定的命令,我得到错误:
The command exited with a non-zero status (number: 1)
所以我的问题是:如何捕获 MacScript
的 return 代码并防止 Excel 被破坏?我试过了:
Dim rc As Integer: rc = MacScript(...)
但是脚本还是出错了!
通常,要防止 do shell script
(因此,间接 MacScript()
)抛出错误,请确保 shell 命令以代码 0
退出。
在你的例子中,为了 仅捕获 shell 命令的退出代码 ,将 ; echo $?
附加到传递给 do shell script
的命令字符串:
简化示例,使用格式错误的 date
命令:
Dim rc As Integer
rc = MacScript("do shell script ""date -nosuchoptions; echo $?""") ' returns 1
echo $?
将(前面的)命令的退出代码输出到 stdout,因此 return 由 do shell script
编辑
- 作为一个 - 理想的 - 副作用,退出代码将设置为
0
,因为 echo
命令成功;因此,整个命令以代码 0
退出,从而防止 do shell script
抛出错误。
注意事项:
- 由于您将
MacScript
的 return 值分配给 Integer
变量,请确保 do shell script
命令的输出可以是 解析为数字.
(上面的命令是安全的,就像你的问题一样,因为前面的命令的标准输出输出被捕获在一个文件中,随后的 echo $?
保证输出一个 "number-looking" 字符串。)
- 如果您的shell命令语法不正确,
MacScript
仍然会抛出错误;您可以使用它来区分语法错误和运行时错误。
相比之下,如果您仍然想 return 命令的 输出 并且只知道 在摘要中 是否有东西出错了:
Dim stdout As String
On Error Resume Next ' ignore runtime errors
stdout = MacScript("do shell script ""date -nosuchoptions""")
If Err.Number <> 0 Then
MsgBox "Something went wrong.", vbExclamation
Else
MsgBox "Captured output: " & stdout, vbInformation
End If
- 请注意,此方法不允许您确定shell命令的特定退出代码,因为Excel VBA 将 any 非零 shell 退出代码转换为一般错误编号
5
(Invalid procedure call or argument
).
最后,您可以组合 2 种方法 - return 命令的输出 和 其特定的退出代码:
Dim stdout As String, rc As Integer, pos As Integer
' Execute the command, and appends its exit code as the *last line* of output.
' Note how both stdout and stderr output are captured via `2>&1`.
stdout = MacScript("do shell script ""{ date; date -nosuchoptions; } 2>&1; echo $?""")
' Extract the last line from the output captured.
pos = InStrRev(stdout, Chr$(13)) ' find last line break (\n has been translated to \r by `do shell script`)
rc = Mid(stdout, pos + 1) # exit code
stdout = Left(stdout, pos - 1) # captured output (only)
If rc <> 0 Then
MsgBox "Command failed with exit code " & rc & "; captured output: " & stdout, vbExclamation
Else
MsgBox "Captured output: " & stdout, vbInformation
End If
注意事项:
- 如果您的shell命令语法不正确,
MacScript
仍然会抛出错误;您可以使用它来区分语法错误和运行时错误。
- 如果您的 shell 命令(
echo $?
之前的命令)没有以 \n
终止其输出,则解析退出代码将不起作用。
In OSX Excel 通过 MacScript
关键字为 运行 Applescript 代码提供功能。我正在 运行ning shell 通过此功能编写代码,它通常如下所示:
MacScript "do shell script ""/usr/bin/whatever"""
最近我决定要捕获输出(和 stderr),因为命令失败了,我想看看错误是什么……所以我这样重写了它:
MacScript "do shell script ""/usr/bin/whatever > /tmp/out 2>&1"""
但是我得到上面的错误。如果我 运行 在 AppleScript 编辑器中给定的命令,我得到错误:
The command exited with a non-zero status (number: 1)
所以我的问题是:如何捕获 MacScript
的 return 代码并防止 Excel 被破坏?我试过了:
Dim rc As Integer: rc = MacScript(...)
但是脚本还是出错了!
通常,要防止 do shell script
(因此,间接 MacScript()
)抛出错误,请确保 shell 命令以代码 0
退出。
在你的例子中,为了 仅捕获 shell 命令的退出代码 ,将 ; echo $?
附加到传递给 do shell script
的命令字符串:
简化示例,使用格式错误的 date
命令:
Dim rc As Integer
rc = MacScript("do shell script ""date -nosuchoptions; echo $?""") ' returns 1
echo $?
将(前面的)命令的退出代码输出到 stdout,因此 return 由do shell script
编辑
- 作为一个 - 理想的 - 副作用,退出代码将设置为
0
,因为echo
命令成功;因此,整个命令以代码0
退出,从而防止do shell script
抛出错误。
注意事项:
- 由于您将
MacScript
的 return 值分配给Integer
变量,请确保do shell script
命令的输出可以是 解析为数字.
(上面的命令是安全的,就像你的问题一样,因为前面的命令的标准输出输出被捕获在一个文件中,随后的echo $?
保证输出一个 "number-looking" 字符串。) - 如果您的shell命令语法不正确,
MacScript
仍然会抛出错误;您可以使用它来区分语法错误和运行时错误。
相比之下,如果您仍然想 return 命令的 输出 并且只知道 在摘要中 是否有东西出错了:
Dim stdout As String
On Error Resume Next ' ignore runtime errors
stdout = MacScript("do shell script ""date -nosuchoptions""")
If Err.Number <> 0 Then
MsgBox "Something went wrong.", vbExclamation
Else
MsgBox "Captured output: " & stdout, vbInformation
End If
- 请注意,此方法不允许您确定shell命令的特定退出代码,因为Excel VBA 将 any 非零 shell 退出代码转换为一般错误编号
5
(Invalid procedure call or argument
).
最后,您可以组合 2 种方法 - return 命令的输出 和 其特定的退出代码:
Dim stdout As String, rc As Integer, pos As Integer
' Execute the command, and appends its exit code as the *last line* of output.
' Note how both stdout and stderr output are captured via `2>&1`.
stdout = MacScript("do shell script ""{ date; date -nosuchoptions; } 2>&1; echo $?""")
' Extract the last line from the output captured.
pos = InStrRev(stdout, Chr$(13)) ' find last line break (\n has been translated to \r by `do shell script`)
rc = Mid(stdout, pos + 1) # exit code
stdout = Left(stdout, pos - 1) # captured output (only)
If rc <> 0 Then
MsgBox "Command failed with exit code " & rc & "; captured output: " & stdout, vbExclamation
Else
MsgBox "Captured output: " & stdout, vbInformation
End If
注意事项:
- 如果您的shell命令语法不正确,
MacScript
仍然会抛出错误;您可以使用它来区分语法错误和运行时错误。 - 如果您的 shell 命令(
echo $?
之前的命令)没有以\n
终止其输出,则解析退出代码将不起作用。