1

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

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

4

4 回答 4

1

VBScript 不会公开该信息,因此您无法从脚本中以编程方式访问它(尽管有边缘情况)。您将需要一个调试器来提取此类信息。或者您可以让另一个脚本解释第一个脚本并跟踪行号(像这样)。不过,我不建议将后者用于任何类型的生产环境。

于 2012-10-07T10:31:26.483 回答
1

不幸的是,这不像在 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
于 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项目上工作来自动添加或删除或重新编号模块中的所有行文件(或独立的 .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
于 2018-08-20T20:45:15.857 回答