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 终止其输出,则解析退出代码将不起作用。