How can I reference an object by a string variable? I feel like there has at be a way to do this other than than using execute and losing Options Explicit
Example (where "Something is the command / method in question":
Dim strObj
Dim D1 : Set D1 = CreateObject("Scripting.Dictionary")
strObj = "D1"
Something(strObj).add "1" , "Car"
msgbox Something(strObj).Item("1")
Thanks!
Only functions (and subs) can be referenced by Set functionReference = GetRef("myFunction") but not objects.
When you want to have a string reference, you have to create one with each object you would want to refer to. You can use a dictionary for that:
Dim foo, bar
Dim StringObjectReference : Set StringObjectReference = CreateObject("Scripting.Dictionary")
' Lets create some objects
Set foo = CreateObject("System.Collections.ArrayList")
Set bar = CreateObject("Scripting.Dictionary")
' Register the objects for referral, now we can reference them by string!
StringObjectReference.Add "foo", foo
StringObjectReference.Add "bar", bar
' Manipulate the objects through their string reference
StringObjectReference("foo").Add "BMW"
StringObjectReference("foo").Add "Chrysler"
StringObjectReference("foo").Add "Audi"
StringObjectReference("foo").Sort
StringObjectReference("bar").Add "Bikes", array("Honda", "Thriumph")
StringObjectReference("bar").Add "Quads", array("Honda", "Kawasaki", "BMW")
' Retrieve values from the objects
' real:
msgbox "My Cars: " & join(foo.ToArray(), ", ")
msgbox "My Bikes: " & join(bar("Bikes"), ", ")
msgbox "My Quads: " & join(bar("Quads"), ", ")
' From reference
msgbox "My Cars: " & join(StringObjectReference("foo").ToArray(), ", ")
msgbox "My Bikes: " & join(StringObjectReference("bar").Item("Bikes"), ", ")
' Shorthand notation (without item)
msgbox "My Quads: " & join(StringObjectReference("bar")("Quads"), ", ")
In the instant you use the content of a string variable to reference some method/function/object in your code, you "lose" the Option Explicit benefits. You can put anything you want inside the variable and it will not be tested until code is executed.
But you can use Option Explicit with Execute. This code
Dim D1
Set D1 = CreateObject("Scripting.Dictionary")
Execute "Option Explicit : D1.Add ""1"",""car"""
Execute "Option Explicit : D2 = D1.Item(""1"")"
WScript.Echo D1.Item("1")
will complain for D2 not been defined. But it will do it at runtime. Comment this line and you will see the Add method working as expected.
Related
In Classic ASP, I have an object, call it bob. This then has a property called name, with let and get methods.
I have a function as follows:
sub append(byref a, b)
a = a & b
end sub
This is simply to make it quicker to add text to a variable. I also have the same for prepend, just it is a = b & a. I know it would be simple to say bob.name = bob.name & "andy", but I tried using the above functions and neither of them work.
The way I am calling it is append bob.name, "andy". Can anyone see what is wrong with this?
Unfortunately this is a feature of VBScript. It is documented in http://msdn.microsoft.com/en-us/library/ee478101(v=vs.84).aspx under "Argument in a class". The alternative is to use a function. Here is an example illustrating the difference. You can run this from the command line using "cscript filename.vbs.
sub append (a, b)
a = a & b
end sub
function Appendix(a, b)
Appendix = a & b
end function
class ClsAA
dim m_b
dim m_a
end class
dim x(20)
a = "alpha"
b = "beta"
wscript.echo "variable works in both cases"
append a, b
wscript.echo "sub " & a
a = appendix(a, b)
wscript.echo "function " & a
x(10) = "delta"
wscript.echo "array works in both cases"
append x(10), b
wscript.echo "sub " & x(10)
x(10) = appendix( x(10), b)
wscript.echo "function " & x(10)
set objAA = new ClsAA
objAA.m_a = "gamma"
wscript.echo "Member only works in a function"
append objAA.m_a, b
wscript.echo "sub " & objAA.m_a
objAA.m_a = appendix(objAA.m_a, b)
wscript.echo "function " & objAA.m_a
Have you tried using with the keyword CALL:
call append (bob.name, "andy")
Classic ASP is fickel about ByRef and ByVal. By default it uses ByRef -- no reason to specify that. If you call a function with parenthesis (without the call), it will pass the variables as ByVal.
Alternatively, you could accomplish the same with:
function append(byref a, b)
append = a & b
end sub
bob.name = append(bob.name, "andy");
Good luck.
As this other answer correctly states, you are facing limitation of the language itself.
The only other option to achieve what you are after as far as I can see it, is to add such sub routine to the class itself:
Public Sub Append(propName, strValue)
Dim curValue, newValue
curValue = Eval("Me." & propName)
newValue = curValue & strValue
Execute("Me." & propName & " = """ & Replace(newValue, """", """""") & """")
End Sub
Then to use it:
bob.Append "name", "andy"
Less elegant, but working.
I am trying to write a piece of code in VBScript to compute the
SHA512 value for a given file. According to MSFT documentation
the ComputeHash method of the SHA512Managed object requires a
Byte array as input. So I used ADODB to read the input file which
SHA512 value is to be computed (Because, AFAIK, there is no way
to build a Byte array in VBScript). However I get a runtime error 5,
'Invalid procedure call or argument' when calling the method. The
variable bar in the code below is of type Byte() - VBScript says.
Could anyone tell me what is going wrong ?
Code :
Option Explicit
'
'
'
Dim scs, ado
Dim bar, hsh
Set scs = CreateObject("System.Security.Cryptography.SHA512Managed")
Set ado = CreateObject("ADODB.Stream")
ado.type = 1 ' TypeBinary
ado.open
ado.LoadFromFile WScript.ScriptFullName
bar = ado.Read
ado.Close
MsgBox TypeName(bar) & "/" & LenB(bar) & "/" & Len(bar),,"Box 1"
' Displays : "Byte()/876/438"
On Error Resume Next
' Attempt 1
Set hsh = scs.ComputeHash(bar)
MsgBox Hex(Err.Number) & "/" & Err.Description,,"Set hsh = "
' Displays : "5/Invalid procedure call or argument"
' Attempt 2
hsh = scs.ComputeHash(bar)
MsgBox Hex(Err.Number) & "/" & Err.Description,,"hsh = "
' Displays : "5/Invalid procedure call or argument"
MsgBox TypeName(scs),,"scs" ' Displays : "SHA512Managed"
Set ado = Nothing
Set scs = Nothing
WScript.Quit
Use
hsh = scs.ComputeHash_2((bar))
(no set, _2 suffix not to pick the other ComputeHash method, pass by value ())
see here.
In this example:
TestSub.vbs
a = "String"
TestSub a
Sub TestSub(a)
MsgBox "Test " & a
End Sub
The Sub function works just fine and displays the text "Test String" in the MsgBox
But in this example (embedded in a HTA)
TestSub2.VBS
Sub getdata
NameID = "name123"
' NameID = 123 ' (This works)
strHTML0 = strHTML0 & _
"<select>" & _
"<option onclick='UpdateSelect("& NameID &")' language='vbscript'>" & _
NameID & _
"</option>" & _
"</select>"
SelectBox.innerHTML = strHTML0
End sub
Sub UpdateSelect(NameID)
MsgBox "Test " & NameID
End sub
The NameID is displayed in the selectbox, but when you call the sub it doesn't display in the messagebox, however, if you set NameID = 123 it displays the integer in the messagebox
Why can it only display integers and how can you make it display a string?
Posted whole .hta on pastebin
You are concatenating strings and must delimiter NameID value in this way:
"<option onclick='UpdateSelect("""& NameID &""")' language='vbscript'>" & _
How to write GUID to .ini file using vbscript?
guid = CreateGUID()
WriteIni "testsection", "ID", guid, "H:\test123.ini"
Function CreateGUID()
CreateGUID = ""
Set objTypeLib = CreateObject("Scriptlet.TypeLib")
Wscript.Echo "GUID: " & objTypeLib.Guid
CreateGUID = objTypeLib.Guid
End Function
The above code is not working properly it appends some other character to the GUID of .ini file. For example:
After writing GUID to test123.ini:
[testsection]
ID=EAE11CC4-F60E-4B21-8AA8-E0CE2ADE5521 5
Here extra character(ex: 5 ) was added. It has to update the file like this:
[testsection]
ID=EAE11CC4-F60E-4B21-8AA8-E0CE2ADE5521
It's a known bug in the Scriptlet.TypeLib object. The Guid property should be 38 characters long, but comes back with a length of 40 with 2 garbage characters at the end. You need to trim the Guid value to avoid the issue:
Function CreateGUID()
CreateGUID = ""
Set objTypeLib = CreateObject("Scriptlet.TypeLib")
CreateGUID = Left(TypeLib.Guid, 38) ' With curly braces: {47BC69BD-06A5-4617-B730-B644DBCD40A9}
' CreateGUID = Mid(TypeLib.Guid, 2, 36) ' Without curly braces: 47BC69BD-06A5-4617-B730-B644DBCD40A9
End Function
You're making this more complicated than it needs to be. I'd suggest to read the INI file into a dictionary of dictionaries, so that a file like this:
[Section1]
value1="foo"
value2="bar"
[Section2]
valueX="baz"
becomes a data structure like this:
+-Section1
| +-value1 -> "foo"
| `-value2 -> "bar"
`-Section2
`-valueX -> "baz"
Then you can simply add a GUID to a given section like this:
section = "Section1"
If Not ini.Exists(section) Then
ini.Add section, CreateObject("Scripting.Dictionary")
End If
ini(section)("ID") = CreateObject("Scriptlet.TypeLib").GUID
and write the data back to a file like this:
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("C:\path\to\your.ini", 2)
For Each section In ini.Keys
f.WriteLine "[" & section & "]"
For Each value In ini(section).Keys
f.WriteLine value & "=" & Chr(34) & ini(section)(value) & Chr(34)
Next
f.WriteLine
Next
f.Close
A while back I wrote a procedure (ParseIni) for parsing INI files into such data structures.
this is the example.
what if the array should be from Mynum1="1" to MyNum100="100"
MyNum1="1"
MyNum2="2"
MyNum3="3"
wat is the best way to declare this.
To iterate through a 100 of these:
Dim myNum(99)
for i = 0 to 99
myNum(i) = i+1
next
for i = 0 to 99
wscript.echo i & " - " & myNum(i)
next
Declare it as an Array:
MyNums = Array("1", "2", "3")
You can access each one with:
foo = MyNums(1)
Which will assign foo to "2".
Technically it is feasible, but it is a very bad practice. You can execute code that is created on the fly with the Execute statement:
Dim i
for i = 1 to 100
Execute "Dim myNum" & i & " : myNum" & i & " = """ & i & """"
' Creates and executes strings like: Dim myNum1 : myNum1 = "1"
next
Again, don't do this if there is any other way, like the use of an array as DesertIvy and ServerGuy showed you.