提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!

某次维护测试需要配置脚本检测网络是否连通,正常手动检测网络是否连通有两个最为常见的办法:一是ping一个主机;二是打开某知名网站。所以脚本检测也顺着这两个思路进行。

关于ping的VBScript实现有 如下代码 可供参考:

Function Ping(strTarget)
  Dim objShell, objExec, strPingResults
  Set objShell = CreateObject("WScript.Shell")
  Set objExec = objShell.Exec("ping -n 2 -w 1000 " & strTarget)
  strPingResults = LCase(objExec.StdOut.ReadAll)
  If InStr(strPingResults, "reply from") Then 
    'WScript.Echo VbCrLf & strTarget & " responded to ping."
    Ping = True
  Else
    'WScript.Echo VbCrLf & strTarget & " did not respond to ping."
    Ping = False
  End If
  Set objExec = Nothing
  Set objShell = Nothing
End Function

这段代码很显然通过Command Shell方式执行ping命令,然后获取输出,判断是否有 reply from ,一般情况下这段代码工作良好,但是对于中文Windows来说ping命令有时会返回中文的输出,例如 来自 xxx.xxx.xxx.xxx 的回复... ,为了使得代码兼容,我们必须再判断关键词“的回复”才可以继续正常运行在中文Windows系统下,但这种方式仍然存在风险,尤其是当操作系统更新,也许过几天微软换个花样,那这里判断依然存在失效的风险。因为机器总是呆萌的,只会按照你的既定流程执行,并不会灵活判断。

另外有网友提出了判断命令执行后的返回值,例如下面的代码片段:

Function Ping(strTarget)
  Dim objShell, ReturnCode
  Set objShell = CreateObject("WScript.Shell")
  ReturnCode = oShell.Run("ping -n 1 -w 300 " & strTarget, 0 , True)
  If ReturnCode = 0 Then
    Ping = True
  Else
    Ping = False
  End If
  Set objShell = Nothing
End Function

先前的ping命令通过 -n 2 对目标主机测试了两次,而本次ping命令则通过 -n 1 参数,测试了一次并立即判断返回值,这样做的问题是在一些网络不太稳定的情况下,测试一次的结果往往是不稳定的,也许第一次没有ping通,而第二次和第三次就ping通了,这样我们并不能说网络是不通的。

Michael Bazarewsky 提出了利用WMI的特性实现Ping的方法 ,更增强了脚本的稳定性和兼容性,代码如下:

' This function returns True if the specified host could be pinged. 
' strHostName can be a computer name or IP address. 
' The Win32_PingStatus class used in this function requires Windows XP or later. 
' This function is based on the TestPing function in a sample script by Don Jones 
' credit: http://www.robvanderwoude.com/vbstech_network_ping.php 
Function Ping(strHostName) 
  ' Standard housekeeping 
  Dim colPingResults, objPingResult, strQuery 
  ' Define the WMI query 
  strQuery = "SELECT * FROM Win32_PingStatus WHERE Address = '" & strHostName & "'" 
  ' Run the WMI query 
  Set colPingResults = GetObject("winmgmts:root\cimv2").ExecQuery(strQuery) 
  ' Translate the query results to either True or False 
  For Each objPingResult In colPingResults 
    If Not IsObject(objPingResult) Then 
      Ping = False 
    Else 
      If objPingResult.StatusCode = 0 Then 
        Ping = True 
      Else 
        Ping = False 
      End If 
      'WScript.Echo "Ping status code for " & strHostName & ": " & objPingResult.StatusCode 
    End If 
  Next 
  Set colPingResults = Nothing 
End Function

好了,Ping的方式检测互联网是否连通是个不错的办法,当然Ping的目标主机可以选择百度(www.baidu.com),或者一些大型的公共DNS服务商,不能选用小众主机哦,万一哪天主机Down了,脚本判断也会出错。

还有一种判断网络是否连通的方式就是网页检测了( 链接 ),但是这种方式会受到ISP的劫持影响,具体代码如下:

Function Ping(strHostName)
  Dim objHTTP
  Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
  strURL = "http://" & strHostName
  objHTTP.Open "GET", strURL, FALSE
  On Error Resume Next
  objHTTP.Send
  If Err.Number = 0 Then
    If objHTTP.statusText = "OK" Then
      Ping = True
      ' MsgBox "Internet is OK"
    Else
      Ping = False
      ' MsgBox "Internet not accessible"
    End If
  Else
    Ping = False
    ' MsgBox "Internet not accessible"
  End If
  Set objHTTP = Nothing
  On Error Goto 0
End Function

所谓的ISP劫持,就是ISP一种推广业务的方式,除了给你弹广告外,还有一种就是当你访问无法访问的页面时会给你自动导向他们的网址导航,可能有网友要问,这也没什么关系吧,至少我证明了网是连通的啊。是的电信级的劫持对于本脚本连接检测影响不大,但是小区宽带也玩劫持的话就有问题了,也许你的主机到小区宽带是连通的,但是这只是一个局域网,小区宽带到Internet并没有连接,那么这样这段脚本的判断也会因此而失效。