2015-03-31 4 views
1

В OSX Excel предусмотрена возможность запуска кода Applescript с помощью ключевого слова MacScript. Я бегу код оболочки с помощью этой функции и в целом выглядит следующим образом:MacScript Неверный вызов или аргумент процедуры

MacScript "do shell script ""/usr/bin/whatever""" 

недавно я решил, что я хотел, чтобы захватить выход (и поток ошибок), так как команда терпела неудачу, и я хотел бы видеть, что была ошибка. .. поэтому я переписал его вот так:

MacScript "do shell script ""/usr/bin/whatever > /tmp/out 2>&1""" 

, но я получаю ошибку выше. если я запускаю данную команду в редакторе AppleScript, я получаю ошибку:

The command exited with a non-zero status (number: 1)

поэтому мой вопрос: как я капкан код возврата MacScript и предотвратить Excel от взлома? Я пробовал:

Dim rc As Integer: rc = MacScript(...) 

но сценарий все еще ломается!

ответ

2

Как правило, для предотвращения возникновения ошибки do shell script (и, следовательно, косвенно, MacScript()) из-за ошибки, убедитесь, что команда оболочки завершена с кодом 0.

В вашем случае, чтобы просто захватить командную оболочку кода с выходом, добавьте ; echo $? в командной строке передается do shell script:

упрощенного примера, используя искаженную date команду:

Dim rc As Integer 
rc = MacScript("do shell script ""date -nosuchoptions; echo $?""") ' returns 1 
  • echo $? выводит код выхода (предшествующей) команды на stdout и поэтому возвращается do shell script
  • как желательный побочный эффект, код выхода будет установлен в 0, потому что команда echo преуспевает; поэтому общая команда выходит с кодом 0, тем самым предотвращая ошибку do shell script.

Предостережение:

  • Поскольку вы присваиваете MacScript «s возвращаемого значения к Integer переменным, убедитесь, что выход в do shell script командования может быть разобран как число.
    (Вышеупомянутая команда безопасна, как и ваша, из вопроса, потому что вывод stdout предыдущей команды записывается в файл, и последующий echo $?, как гарантируется, выводит строку с номером.)
  • Если ваш команда оболочки синтаксически неверно, MacScript все равно выдает ошибку; вы можете использовать это, чтобы различать синтаксис и ошибки времени выполнения.

Если, напротив, вы все еще хотите, чтобы вернуть вывод комманд и просто знать, в абстрактномпошел ли что-то не так:

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 
  • Обратите внимание, что этот метод не Позволяет вам определить команду командной строки оболочки код выхода, be причина Excel VBA переводит любой ненулевой код выхода оболочки в общий номер ошибки 5 (Invalid procedure call or argument).

Наконец, вы можете объединить в 2 подхода - возвращает вывод команды и его конкретный код выхода:

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 

Предостережения:

  • Если ваша команда оболочки синтаксически неверно, MacScript все равно выдаст ошибку; вы можете использовать это, чтобы различать синтаксис и ошибки времени выполнения.
  • Если ваша команда оболочки (предшествующая echo $?) не завершает свой вывод с помощью \n, разбор кода выхода не будет работать.
+0

ничего себе. спасибо за ясность и большую детализацию. больше, чем я ожидал :) +1 – ekkis

+0

@ekkis: Мое удовольствие. Я сам чему-то научился. – mklement0

Смежные вопросы