1

__LINE__のようなコードのポイントでプログラムでvbscriptの行の行番号を取得する方法、またはより理想的には現在の関数がpythonのスタックモジュールのように呼び出された場所の行番号を取得する方法を知りたいので、私は再利用可能なデバッグ関数(およびコードが配置されているファイル)を記述できますが、エディターで行番号をオンにする方法を知りたくありません。

また、関数の呼び出し、文字列としての変数の型など、抽出できる同様の有用な情報があれば教えてください。

4

4 に答える 4

1

VBScriptはその情報を公開しないため、スクリプト内からプログラムでアクセスすることはできません(エッジケースにもかかわらず)。この種の情報を抽出するには、デバッガーが必要になります。または、別のスクリプトで最初のスクリプトを解釈し、行番号を追跡することもできます(このように)。ただし、どのような種類の本番環境にも後者はお勧めしません。

于 2012-10-07T10:31:26.483 に答える
1

残念ながら、これはRubyやPythonのようには機能しません。私が解決した次善の策は、問題が発生する可能性のあるすべての場所でエラー処理関数を呼び出すことです。この関数のパラメーターの数値は、エディターでマクロを実行するたびに調整されます(テキストパッドを使用し、\ iは正規表現で自動番号付けされます)。エディターがこれをサポートしていない場合は、これを行うスクリプトを作成できます。したがって、エラーが発生すると、エラー処理関数が呼び出された番号でログに記録され、#number#を探すことでソースで簡単に見つけることができます。

これはaspとvbsの両方で使用できますが、vbsの場合はもっと簡単な方法があります。textpadやsublimletextなどの一部のエディターでは、vbsスクリプトを実行し、出力をタブに表示できます。エラーが発生した場合は、エラーメッセージのある行をダブルクリックして、その行でスクリプトを開きます。これも正規表現によって行われます。テキストパッド用のものが必要な場合はお知らせください。

on error resume next
'initialize constants DEBUGLEVEL and LOGFILE
'initialize strHostName

'some code
oConn.execute(sql)

if not LogError("#1#") then
  'do the things if successfull, otherwise log error with number
end if

'again some code
if not LogError("#2#") then
  'do the things if successfull, otherwise log error with number
end if

'the debug and log functions
function LogError(errornumber)
  'LogError\(\"#[0-9]+#\"\) replace by LogError("#\i#")
  if err.number <> 0 then
    call debug("<name of script>/Logerror","","","Errornumber:" _
      & errornumber & " " & err.number & " " & err.description & " " _
      & err.source)
    LogError = True
    err.clear
    errors = errors+1
  else
    LogError = False
  end if
end function

function Debug (pagina, lijn, varnaam, varinhoud)
  if DEBUGLEVEL > 0 then
    const forReading = 1, forWriting = 2, forAppending = 8, CreateFile = True
    dim fs,f, var, strHostName
    set fs=CreateObject("Scripting.FileSystemObject")
    strHostName    = fs.GetFileName(WScript.FullName)
    if fs.FileExists(LOGFILE) then
      set f=fs.OpenTextFile(LOGFILE, forAppending)
    else
      set f=fs.OpenTextFile(LOGFILE, forWriting,true)
    end if
    var = now & " " & pagina & ":" & lijn & ":" & varnaam & ":" & varinhoud
    f.WriteLine var
    if LCase(strHostName) = "cscript.exe" then 'debugging
      if DEBUGLEVEL > 1 then
        wscript.echo var
      end if
    end if
    f.Close
    set f=Nothing
    set fs=Nothing
  end if
  debug = true
end function
于 2012-10-08T08:22:31.587 に答える
0

関数の外部で発生している限り、次のように機能します。

スクリプトの開始時に自動エラー処理がオフにOn Error Resume Nextなっているため、何かを実行する前にスクリプトが終了することはありません。ただし、エラー処理をオンに戻してOn Error GoTo 0、自分で例外を発生させることができます。これにより、デバッグメッセージに加えて行番号が出力されます。

例えば:

On Error Resume Next
server = WScript.Arguments(0)
If Err.Number <> 0 Then
    WScript.Echo("Need to pass in an argument!")
    On Error GoTo 0
    Err.Raise(1)
End if

引数なしでこれを実行すると、次の出力が得られます。

Need to pass in an argument!
C:\script.vbs(6, 5) Microsoft VBScript runtime error: Unknown runtime error

「6」は、例外が発生した行番号を示します。

このようにして、カスタム出力を印刷できます。また、エラーが発生した行を知ることができます。

于 2014-11-04T01:17:21.780 に答える
-1

はい!

正確なエラー行番号を取得する方法はありますが、古代のプログラミングツールについて話しているので、それは醜いです。

そして、はい、特にコードが多くのユーザーの前で実行される場合は、それだけの価値があります。そうすれば、バグの切り分けと再現を乗り越えて、問題を解決することができます。

以下のコード行の最後の変数「Erl」をよく見てください。これは、VBスクリプトプロセッサが保持する文書化されていないグローバル変数です。

Dim sErrorMsg as String
sErrorMsg = Err.Description & "(" & Err.Number & ")" & vbNewLine & "Source: " & Err.Source & vbNewLine & "At line number: " & Erl

そのグローバルな「Erl」変数から何かを取得するには、以下に示すように、コードの各行の先頭にその値を(手動で)**設定する必要があります。行番号を設定することに注意してください。特定の行の番号を設定するのを忘れた場合、Erlは最後に設定された値を報告します。ゼロ除算のエラー行を参照してください。エラーの原因となった行の先頭に行番号の値を設定しなかったため、上記で設定した行番号が報告されます。

組み込みのコールスタックはあるとは思いますが、わかりません。あなたがそれを理解したら私に知らせてください、今のところ私はスタックを構築するためにモジュールレベルの変数を使用しています。

このコードサンプルの下の最後にあるその他のヒント

Sub WhatEverSub ()
2        Const iColIdxPageNbr As Integer = 2
3        Const iColIdxDefinition As Integer = 3

5        Dim oDoc_Source As Document
6        Dim oDoc_Target As Document



10        Dim oTable As Table
11        Dim oRange As Range
12        Dim n As Long
13        Dim strAllFound As String
14        Dim Title As String
15        Dim Msg As String

        On Error GoTo PrepErrorHandler
            Dim xyz As Long
            xyz = Rnd(3) / 0
16
17        Title = "Evil Finder - This program is about doing something important for the world"
18
19        'Show msg - stop if user does not click Yes
20        Msg = "This macro finds all evil things consisting of 2 or more " & _
            "uppercase letters and extracts the hex representation to a table " & _
            "in a new document." & vbNewLine & vbNewLine & _
            "Do you want to continue?"

21        If MsgBox(Msg, vbYesNo + vbQuestion, Title) <> vbYes Then
22            Exit Sub
23        End If

(... whatever code ...)

820        Application.ScreenUpdating = True
830        If n = 1 Then
840            Msg = "No evil things were found. Need to find better detection tool"
850            oDoc_Target.Close savechanges:=wdDoNotSaveChanges
860        Else
870            Msg = "Finished extracting " & n - 1 & " evil thing(s) to a new document."
880        End If

PrepErrorResumeLine:
890        MsgBox Msg, vbOKOnly, Title

        'Clean up
1000        Set oRange = Nothing
1010        Set oDoc_Source = Nothing
1020        Set oDoc_Target = Nothing
1030        Set oTable = Nothing

Exit Sub

PrepErrorHandler:
        Msg = Err.Description & "(" & Err.Number & ")" & vbNewLine & "Source: " & Err.Source & vbNewLine & "At line number: " & Erl
        Resume PrepErrorResumeLine
End Sub

**その他のヒント:1)エラー行番号の値を手動で設定する場合、VBプロジェクトで直接作業することにより、モジュール内のすべての行の追加、削除、または番号の付け直しを自動化するユーティリティを作成しました(10年以上前)。ファイル(またはスタンドアロンの.vbsファイル)ですが、以下は基本的な処理を行いますが、いくつかの手動調整が残っています...

MS Excelを使用してVBコード行番号を設定しますa)列Cにコードを貼り付けますb)列Aの最初のセル値を10に設定し、2番目を20に設定し、コピーを下にドラッグして、コードの最後の行/行に到達するまで自動インクリメントします列Bc)列Bに次の数式を貼り付け、コピーを下にドラッグ= A1&REPT( ""、8 --LEN(A1))d)列BとCをVBコードペインにコピーして戻します。

Wordを使用して行番号を削除し、コードを貼り付け、CTRL + Hを押して、ワイルドカードがオンになっていることを確認します([詳細]ボタンをクリックします)。次の設定を入力します。FIND[^ 13] [0-9] { 4} REPLACE ^ p完了!

2)各行に少なくとも10ずつ番号を付けて、変更の下の各行に番号を付け直さなくても、最後の最後に数行でくさびを付けることができるようにします。

3)エラー時再開次は悪であり、デバッグに多くの時間を要します!少なくとも90%の確率で、特定のハンドラーを使用するか、何も使用しないでください。エラーから回復する方法がまだわからない場合は、RESUME NEXTを使用してエラーを消音しないでください。代わりに、すべての詳細をログに記録し(Erlを使用)、実行時ログから学習して、文字OではなくGoTo0'ゼロを使用してください。残りのエラーがコールスタックをバブルアップさせるため。

On Error GoTo MyErrorHandlerSection
(... write your risky code here ...)
On Error GoTo 0
'the line immediately above disables all error handling in the current function, if any error happens, it will be passed to the calling function

を使用して危険なコードの別のチャンクがある場合、同じ関数に別の処理セクションを追加することを妨げるものは何もありません

On Error GoTo MySecondErrorHandlerSection
于 2018-08-20T20:45:15.857 に答える