VBScript - Korzystanie z obsługi błędów

84

Chcę używać VBScript do wychwytywania błędów i rejestrowania ich (np. W przypadku błędu „zarejestruj coś”), a następnie wznów następny wiersz skryptu.

Na przykład,

Przy błędzie Wznów Dalej
'Wykonaj Krok 1
'Wykonaj krok 2
Wykonaj krok 3

Gdy błąd wystąpi w kroku 1, chcę, aby zarejestrował ten błąd (lub wykonał inne niestandardowe funkcje), a następnie wznowił od kroku 2. Czy to możliwe? i jak mogę to wdrożyć?

EDYCJA: Czy mogę zrobić coś takiego?

W przypadku błędu Wznów myErrCatch
Wykonaj krok 1
Wykonaj krok 2
Wykonaj krok 3

myErrCatch:
błąd dziennika
Wznów Dalej
apandit
źródło
1
Odpowiedź Dylana jest tak dobra, jak VB w dziale obsługi błędów. Dlatego zawsze używałem Javascript, kiedy mogłem ujść na sucho.
wcm

Odpowiedzi:

161

VBScript nie ma pojęcia o rzucaniu lub przechwytywaniu wyjątków, ale środowisko wykonawcze udostępnia globalny obiekt Err, który zawiera wyniki ostatniej wykonanej operacji. Po każdej operacji należy jawnie sprawdzić, czy właściwość Err.Number jest różna od zera.

On Error Resume Next

DoStep1

If Err.Number <> 0 Then
  WScript.Echo "Error in DoStep1: " & Err.Description
  Err.Clear
End If

DoStep2

If Err.Number <> 0 Then
  WScript.Echo "Error in DoStop2:" & Err.Description
  Err.Clear
End If

'If you no longer want to continue following an error after that block's completed,
'call this.
On Error Goto 0

Składnia „On Error Goto [etykieta]” jest obsługiwana przez Visual Basic i Visual Basic for Applications (VBA), ale VBScript nie obsługuje tej funkcji języka, więc musisz użyć opcji On Error Resume Next, jak opisano powyżej.

Dylan Beattie
źródło
3
Możesz zmienić WScript.Echo w instrukcji If, aby wywołać funkcję lub podrzędną, co z kolei może zamknąć aplikację, zarejestrować błąd itp.
StormPooper
„zawiera powtórzenia ostatniej wykonanej operacji”. Czy to prawda? Wygląda na to, że dostaje ostatni błąd, co jest dużą różnicą.
Damien Golding
Pomimo, że dokumentacja MS sugeruje, że err.clearnależy ją stosować po każdym sprawdzeniu obiektu, aby zapobiec wyzwalaniu przez poprzednie błędy następnego sprawdzenia (np. Technet.microsoft.com/en-us/library/ee692852.aspx ), z mojego doświadczenia errwynika, że ​​jest to wyczyszczone ” sama z siebie ”w miarę postępu skryptu. Bez dalszych testów, przypuszczam, że wykorzystuję czyszczenie obiektów errjako produkt uboczny ich wewnętrznych operacji.
user66001
@ user66001 Zgoda, ale nadal bezpieczniej jest jawnie wywołać Err.Clear.
Lankymart
12

Zauważ, że On Error Resume Nextnie jest to ustawione globalnie. Możesz umieścić swoją niebezpieczną część kodu, np. W funkcji, która zostanie natychmiast przerwana, jeśli wystąpi błąd, i wywołać tę funkcję z pod zawierającej poprzednią OERNinstrukcję.

ErrCatch()

Sub ErrCatch()
    Dim Res, CurrentStep

    On Error Resume Next

    Res = UnSafeCode(20, CurrentStep)
    MsgBox "ErrStep " & CurrentStep & vbCrLf & Err.Description

End Sub

Function UnSafeCode(Arg, ErrStep)

    ErrStep = 1
    UnSafeCode = 1 / (Arg - 10)

    ErrStep = 2
    UnSafeCode = 1 / (Arg - 20)

    ErrStep = 3
    UnSafeCode = 1 / (Arg - 30)

    ErrStep = 0
End Function
omegastripes
źródło
1
Nie jest to najlepszy przykład, jaki kiedykolwiek widziałem, ale rozumiem koncepcję.
Lankymart
7
@Lankymart, czy mógłbyś połączyć jaśniejszy przykład, który widziałeś, czy zamiast tego zasugeruj, jak omegastripes mogą ulepszyć ten przykład?
Dominick
3
Przez sekundę odniosłem wrażenie, że przegapiłem nowy paradygmat inżynierii oprogramowania zwany „omegastripes” lol
TheBlastOne
4

Możesz przegrupować wywołania funkcji kroków w funkcji fasady:

sub facade()
    call step1()
    call step2()
    call step3()
    call step4()
    call step5()
end sub

Następnie pozwól, aby obsługa błędów była w górnej funkcji, która wywołuje fasadę:

sub main()
    On error resume next

    call facade()

    If Err.Number <> 0 Then
        ' MsgBox or whatever. You may want to display or log your error there
        msgbox Err.Description
        Err.Clear
    End If

    On Error Goto 0
end sub

Teraz załóżmy, że step3()wywołuje błąd. Ponieważ facade()nie ma obsługi błędów (jest nie On error resume next w facade()), błąd zostanie zwrócony main()i step4()i step5()nie będą realizowane.

Twoja obsługa błędów jest teraz refaktoryzowana w 1 bloku kodu

Cid
źródło
1

Jestem wyjątkowo nowy w VBScript, więc może to nie być uważane za najlepszą praktykę lub może istnieć powód, dla którego nie powinno się tego robić w ten sposób, którego jeszcze nie jestem świadomy, ale to jest rozwiązanie, które wymyśliłem, aby przyciąć zmniejszyć ilość kodu rejestrowania błędów w moim głównym bloku kodu.

Dim oConn, connStr
Set oConn = Server.CreateObject("ADODB.Connection")
connStr = "Provider=SQLOLEDB;Server=XX;UID=XX;PWD=XX;Databse=XX"

ON ERROR RESUME NEXT

oConn.Open connStr
If err.Number <> 0 Then : showError() : End If


Sub ShowError()

    'You could write the error details to the console...
    errDetail = "<script>" & _
    "console.log('Description: " & err.Description & "');" & _
    "console.log('Error number: " & err.Number & "');" & _
    "console.log('Error source: " & err.Source & "');" & _
    "</script>"

    Response.Write(errDetail)       

    '...you could display the error info directly in the page...
    Response.Write("Error Description: " & err.Description)
    Response.Write("Error Source: " & err.Source)
    Response.Write("Error Number: " & err.Number)

    '...or you could execute additional code when an error is thrown...
    'Insert error handling code here

    err.clear
End Sub
MistyDawn
źródło
1
To jest ASP Classic, a nie zwykły stary VBScript
Jobbo