在VBS中将变量设置为变量的问题

时间:2011-08-23 11:28:07

标签: vbscript scope secure-crt

在VBS中,我与SecureCRT一起使用以自动化思科设备上的某些进程,我(非常关注)以下代码:

Sub prConnectToHost(strConnectHost)

  'If no host is passed into subroutine then we need to prompt for one.
  If strConnectHost = "" Then strConnectHost = LCase(crt.Dialog.Prompt("Enter hostname or IP address:", "Connect to a host", strHost, False))

  strHost = strConnectHost

  'If user hits Cancel or hits Ok with no hostname entered then exit.
  If strHost = "" Then
    booReconnect = False
    Exit Sub
  End If

  'Write to connection log
  Call prWriteToConnectionLog

  'Run command capture subroutine.
  Call prCommandLoop

  Set intWaitString = Nothing:  Set strScreenGet = Nothing
  Set strLatestScriptVersion = Nothing:  Set strConnectHost = Nothing
End Sub

Sub Main有一个这样的部分:

Do While booReconnect = True
  Call prConnectToHost("")
Loop

crt.Dialog.PromptMsgBox相同,只是它以窗口而不是屏幕为中心,因此它更整洁。变量strHost是实际的主机名字符串,它在脚本中是全局的,包含我们要连接的主机名。它在Prompt行中用作默认文本,其想法是,如果您断开连接并设置了booReconnect标记,则会再次调用此Sub,并在下次启用时提示输入旧的主机名 - 如果您第一次拼写错误,或者连接到一堆名称相似的设备,则会很有用。

您可以在prCommandLoop的末尾看到我们拨打Sub的位置,这是一个使用名为crt Function的{​​{1}}的循环,该脚本暂停它找到一个特定的字符串序列。当它发生时,它会触发一些东西,然后循环回来,直到它再次等待。

其中一个自动化命令检测是否存在连接菜单(因此我们已退出路由器会话)并提示用户输入另一个主机名。

重要的一点是最后的变量clearup - WaitForStrings。如果我将其保留并立即退出设置Set strConnectHost = Nothing的{​​{1}},则只要prCommandLoop被应用,booReconnect就会死亡 - 如果我尝试引用它,则会收到错误{ {1}}。我尝试在Set strConnectHost = Nothing的末尾添加strHost行,证明了这一点。

奇怪的是,如果我先在Object Variable not set中选择一个不同的自动化命令然后退出会话,MsgBox strHost似乎不会打扰任何人。

任何人都可以帮我解释为什么这是一个问题,因为它令我感到困惑。我可以轻松解决这个问题(不在Sub Sub的末尾发布prCommandLoop),但我只想了解问题所在。

1 个答案:

答案 0 :(得分:0)

设置用于将对象分配给变量。把Nothing想象成一个非常特殊的对象

>> WScript.Echo IsObject(Nothing)
>>
-1

仅用于指示变量的空虚。您的

Set strConnectHost = Nothing

将此Nothing分配给strConnectHost。在那之后,变量什么都不做 - 它保存了无法打印或用于计算或被要求做方法的空对象。

类型前缀欺诈(* str * ConnectHost)应该提醒您这很可疑。你使用字符串(和数字?);清除/重置它们使用(简单)赋值为Empty:

>> strConnectHost = Empty
>>
>> WScript.Echo IsEmpty(strConnection)
>>
-1

或具有合适的值:

intWaitString = -1 ' or 0 ...

(假设intWaitString不是另一种类型前缀欺诈)。

第二次尝试:

我假设你像这样打电话给你的潜水员:

strHost = "SomeHost"
prConnectToHost strHost

您子的相关摘要是:

Sub prConnectToHost( [ByRef] strConnectHost)
  ...
  Set strConnectHost = Nothing
End Sub

由于VBScript使用引用传递参数作为默认值,因此您的修改 更改调用者变量strHost。这也发生在非对象变量上:

  Dim sVar : sVar = "String 0"
  WScript.Echo 0, sVar
  changeString sVar
  WScript.Echo 1, sVar

  Sub changeString( sByRefVar )
    sByRefVar = "String 1: changed by changeString( ByRef sByRefVar )"
  End Sub

输出:

0 String 0
1 String 1: changed by changeString( ByRef sVar )

在您的情况下,修改将Nothing分配给被调用的变量 str中的strConnectHost和调用者级别的strHost。正如我之前所说, 这使得变量无用(除了测试Is Nothing之外)。

我希望这能解释strHost的崩溃。

WRT'内存管理':除了非常特殊的情况,你不需要 VBScript中的clear / reset / SetToNothing变量。在你的中使用局部变量 子/功能就是必要的。如果您决定使用全局变量 并且自己管理他们的状态,你必须注意变量类型: 从对象更改类型(包括Nothing)< =>非对象和撒谎 关于误导类型前缀的类型是危险的/可靠的方法。 如果您认为必须清除strHost,请将“空”或“”分配给strConnectHost。

下一次添加

所有VBScript变量都是变体,但并非所有变体都是相同的:

>> s0 = "string"
>> s1 = CStr( 12.35 )
>> WScript.Echo TypeName( s0 ), TypeName( s1 )
>>
String String
>> n0 = 1
>> n1 = CByte( n0 )
>> WScript.Echo TypeName( n0 ), TypeName( n1 )
>>
Integer Byte

TypeName()和VarType()显示子类型,progammer可以使用一组 C[hange/onvertTo]<Type>()用于强制执行它们 - 在某种程度上,作为任务 可能会改变“引擎盖下的类型”。

>> WScript.Echo TypeName( n0 ), TypeName( n1 )
>>
Integer Byte
>> n0 = 1.1
>> n1 = 2 ^ 20
>> WScript.Echo TypeName( n0 ), TypeName( n1 )
>>
Double Double

甚至出现类型不匹配错误:

>> WScript.Echo Nothing
>>
Error Number:       13
Error Description:  Type mismatch
>>

>> WScript.Echo s0 Is Nothing
>>
Error Number:       424
Error Description:  Object required

所以子类型很重要。有些人认为类型前缀不合适,但其他人看到 它们在弱类型语言中作为有价值的帮助。如果您决定使用它们,那么 应该正确使用它们 -

   Set strWhatEver = objWhatever
   objWhatever = intWhatever
   intWhatever = objWhatever
   If strWhatEver = intWhatever Then

所有气味(没有注意类型,很难在以后的代码中确定错误)。