__LINE__のようなコードのポイントでプログラムでvbscriptの行の行番号を取得する方法、またはより理想的には現在の関数がpythonのスタックモジュールのように呼び出された場所の行番号を取得する方法を知りたいので、私は再利用可能なデバッグ関数(およびコードが配置されているファイル)を記述できますが、エディターで行番号をオンにする方法を知りたくありません。
また、関数の呼び出し、文字列としての変数の型など、抽出できる同様の有用な情報があれば教えてください。
__LINE__のようなコードのポイントでプログラムでvbscriptの行の行番号を取得する方法、またはより理想的には現在の関数がpythonのスタックモジュールのように呼び出された場所の行番号を取得する方法を知りたいので、私は再利用可能なデバッグ関数(およびコードが配置されているファイル)を記述できますが、エディターで行番号をオンにする方法を知りたくありません。
また、関数の呼び出し、文字列としての変数の型など、抽出できる同様の有用な情報があれば教えてください。
VBScriptはその情報を公開しないため、スクリプト内からプログラムでアクセスすることはできません(エッジケースにもかかわらず)。この種の情報を抽出するには、デバッガーが必要になります。または、別のスクリプトで最初のスクリプトを解釈し、行番号を追跡することもできます(このように)。ただし、どのような種類の本番環境にも後者はお勧めしません。
残念ながら、これは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
関数の外部で発生している限り、次のように機能します。
スクリプトの開始時に自動エラー処理がオフに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」は、例外が発生した行番号を示します。
このようにして、カスタム出力を印刷できます。また、エラーが発生した行を知ることができます。
はい!
正確なエラー行番号を取得する方法はありますが、古代のプログラミングツールについて話しているので、それは醜いです。
そして、はい、特にコードが多くのユーザーの前で実行される場合は、それだけの価値があります。そうすれば、バグの切り分けと再現を乗り越えて、問題を解決することができます。
以下のコード行の最後の変数「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