我想知道如何在 __LINE__ 之类的代码处以编程方式获取 vbscript 中一行的行号,或者更理想的是一种获取当前函数被调用的行号的方法,例如 python 的堆栈模块,所以我可以编写一个可重用的调试函数(以及代码所在的文件),不,我不想知道如何在我的编辑器中打开行号。
我现在还想提取任何类似的有用信息,例如调用函数、变量类型为字符串等。
我想知道如何在 __LINE__ 之类的代码处以编程方式获取 vbscript 中一行的行号,或者更理想的是一种获取当前函数被调用的行号的方法,例如 python 的堆栈模块,所以我可以编写一个可重用的调试函数(以及代码所在的文件),不,我不想知道如何在我的编辑器中打开行号。
我现在还想提取任何类似的有用信息,例如调用函数、变量类型为字符串等。
不幸的是,这不像在 Ruby 和 Python 中那样工作。我想出的下一件最好的事情是在任何可能出错的地方调用错误处理函数。每次我在编辑器中执行宏时,都会调整此函数参数中的数字(我使用文本板,\i 是正则表达式中的自动编号)。如果您的编辑器不支持此功能,您可以编写一个脚本来执行此操作。因此,当发生错误时,会记录调用错误处理函数的编号,您可以通过查找#number# 轻松地在源代码中找到它。
这对 asp 和 vbs 都可用,但对于 vbs 有更简单的方法。一些编辑器,如 textpad 或 sublimle text 让您执行 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项目上工作来自动添加或删除或重新编号模块中的所有行文件(或独立的 .vbs 文件),但下面会处理基本的,剩下一些手动调整......
使用 MS Excel 设置 VB 代码行 #s a) 在 C 列中粘贴代码 b) 将 A 列的第一个单元格值设置为 10,第二个设置为 20,然后将副本向下拖动以自动递增,直到到达最后一行/行代码列 B c) 在列 B 中粘贴以下公式并向下拖动复制 =A1 & REPT(" ", 8 - LEN(A1)) d) 将列 B 和 C 复制回 VB 代码窗格等瞧!
删除行号以使用 Word 进行主要编辑粘贴代码,按 CTRL + H 并确保选中通配符(单击“更多”按钮)填写以下设置 FIND [^13][0-9]{ 4} 替换 ^p 完成!
2) 至少以 10 的增量为每行编号,这样您就可以在最后一分钟插入几行,而不必在更改下方重新编号每一行
3) On Error Resume Next 是邪恶的,会花费你大量的调试时间!至少 90% 的时间,应该使用特定的处理程序,或者什么都不用。如果您还不知道如何从错误中恢复,请不要使用 RESUME NEXT 将其静音,而是记录所有详细信息(使用 Erl)并从运行时日志中学习并使用 GoTo 0 'Zero,而不是字母 O让其余的错误冒泡调用堆栈。
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