Проблема с переменной, установленной на переменную в VBS - PullRequest
0 голосов
/ 23 августа 2011

В VBS, который у меня есть, который я использую вместе с SecureCRT для автоматизации некоторых процессов на устройствах Cisco, у меня есть (очень урезанный) следующий код:

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.Prompt - это то же самое, что и MsgBox, только он центрируется на окне, а не на экране, поэтому он немного аккуратнее. Переменная strHost является фактической строкой имени хоста, которая является глобальной в сценарии и содержит имя хоста, к которому мы хотим подключиться. Он используется в строке Prompt в качестве текста по умолчанию, идея состоит в том, что если вы отключитесь и установлен флаг booReconnect, этот Sub будет вызван снова, и в следующий раз вам будет предложено ввести имя хоста старое один из них полезен, если вы в первый раз написали его неправильно или подключаетесь к группе устройств с похожим названием.

Вы можете видеть, где мы вызываем prCommandLoop в конце этого Sub, который представляет собой цикл, который использует crt Function с именем WaitForStrings, который удерживает скрипт до тех пор, пока он не найдет определенную последовательность строк. Когда он это делает, он запускает некоторые вещи, а затем возвращается назад, пока снова не ждет.

Одна из команд автоматизации обнаруживает наличие меню подключения (поэтому мы завершили сеанс маршрутизатора) и запрашивает у пользователя другое имя хоста для подключения.

Важный бит находится в конце очистки переменной - Set strConnectHost = Nothing. Если я оставлю это и сразу выйду из prCommandLoop с установленным booReconnect, как только будет применено Set strConnectHost = Nothing, умрет strHost - если я попытаюсь сослаться на него, я получу ошибку Object Variable not set. Я экспериментировал с положением линии MsgBox strHost прямо в конце Sub, что доказало это.

Странно то, что если я сначала выберу другую команду автоматизации в prCommandLoop, а затем выйду из сеанса, Set strConnectHost = Nothing, кажется, никого не беспокоит.

Может кто-нибудь помочь мне объяснить, почему это проблема, потому что она сбивает меня с толку. Я могу легко обойти это (не выдав Set strConnectHost = Nothing в конце prConnectToHost Sub), но я просто хочу понять, в чем проблема.

1 Ответ

0 голосов
/ 23 августа 2011

Set используется для назначения объектов переменным. Ничто не думайте как особый объект

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

, который полезен только для указания пустоты переменной. Ваш

Set strConnectHost = Nothing

назначает это Ничто для strConnectHost. После этого переменная бесполезна - она ​​содержит пустой объект, который нельзя распечатать или использовать в вычислениях или попросить сделать методы.

Мошенничество с префиксом типа (* str * ConnectHost) должно предупредить вас, что это подозрительно. Вы работаете со строками (и числами?); чтобы очистить / сбросить их, используйте (простое) назначение с пустым:

>> 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 )

В вашем случае модификация ничего не присваивает переменной, которая называется strConnectHost в Sub и strHost на уровне вызывающего. Как я сказал ранее, что делает переменную бесполезной (кроме проверки на Is Nothing).

Надеюсь, это объясняет забивание strHost.

WRT 'управление памятью': за исключением особых случаев, вам не нужно Переменные сброса / сброса / SetToNothing в VBScript. Использование локальной переменной в вашем Subs / Functions это все что нужно. Если вы решили использовать глобальные переменные и управляя своим состоянием самостоятельно, необходимо обратить внимание на типы переменных: Изменение типа от объекта (включая Ничто) <=> не объект и ложь вводить в заблуждение префиксы типов опасно / верный путь к разрушению. Если вы считаете, что должны очистить strHost, присвойте Empty или "" 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 () показывают подтипы, и программатор может использовать набор 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

все пахнет (не обращая внимания на типы и трудно определить ошибки в последующем коде).

...