如何在VBSCRIPT中提取相当于__LINE __,__ FILE __等的上下文信息

时间:2012-10-07 06:17:48

标签: debugging logging vbscript introspection printf-debugging

我想知道如何在程序上以编程方式获取vbscript中一行的行号,如__LINE__或更理想的方式来获取调用当前函数的行号,如python的堆栈模块,所以我可以编写一个可重用的调试函数(以及代码所在的文件),不,我不想知道如何在我的编辑器中打开行号。

此外,我想现在可以提取任何类似的有用信息,如调用函数,变量类型为字符串等。

4 个答案:

答案 0 :(得分:1)

VBScript不会公开该信息,因此您无法从脚本(edge cases notwithstanding)中以编程方式访问它。您将需要debugger来提取此类信息。或者您可以使用另一个脚本解释第一个脚本并跟踪行号(like this)。不过,我不建议将后者用于任何类型的生产环境。

答案 1 :(得分:1)

不幸的是,这种方式不像Ruby和Python那样。我解决的下一个最好的事情就是在出现问题的地方调用错误处理函数。每次我在编辑器中执行宏时,都会调整此函数参数中的数字(我使用textpad,\ i是正则表达式中的自动编号)。如果您的编辑器不支持此功能,您可以编写一个执行此操作的脚本。因此,当发生错误时,会记录错误处理函数被调用的编号,您可以通过查找#number#轻松地在源代码中找到它。

这适用于asp和vbs,但对于vbs,有一种更简单的方法。 某些编辑器(如textpad或sublimle文本)允许您执行vbs脚本,在选项卡中显示输出,如果产生错误,请双击带有errormessage的行,该行将在该行打开脚本。这也是通过正则表达式完成的。如果你需要一个用于写字板的话,请告诉我。

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

答案 2 :(得分: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

&#34; 6&#34;是指引发异常的行号。

通过这种方式,您可以打印自定义输出,并且您还可以知道错误发生在哪一行。

答案 3 :(得分:-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项目文件(或独立的.vbs文件)来自动添加,删除或重新编号模块中的所有行。 ,但以下内容将介绍基本内容,还需要进行一些手动调整...

使用MS Excel设置VB代码行号     a)将代码粘贴到C列中     b)将A列的第一个单元格值设置为10,第二个设置为20,然后向下拖动副本以自动递增,直到到达B列的最后一行代码行     c)在B列中粘贴以下公式,然后向下拖动复制= A1&REPT(“”,8-LEN(A1))     d)将B和C列复制回VB代码窗格中,瞧!

删除行号以使用Word进行主要编辑     将代码粘贴到     按CTRL + H并确保已选中通配符(单击“更多”按钮)     填写以下设置         找             [^ 13] [0-9] {4}         更换             ^ p 完成!

2) 每行至少以10为增量编号,因此您可以在最后一刻插入几行,而不必在更改以下重新编号每行

3)在错误恢复上,下一步是邪恶的,将花费您大量的调试时间! 至少有90%的时间应该使用一种特定的处理程序,或者什么也不使用。如果您尚不知道如何从错误中恢复,请不要使用RESUME NEXT将其静音,而是记录所有详细信息(使用Erl)并从运行时日志中学习,并使用GoTo 0'0(不是字母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