I am making a simple questionnaire for a client in Classic ASP.
The idea is that there will be 10 questions. The user registers and is being sent to the first question. When this is answered they move on to the 2nd question etc.
Questions can be skipped and returned to at a later date, and each question can only be answered once.
I have a comma separated list in the database of each question a user has answered.
So, a user logs in and an array is created with the list of answered questions.
What would be the best way to loop through this list and go to the first unanswered question?
An example of the array of answered questions would look something like this "1,4,6"
so this user would have answered questions number 1, 4 and 6. When a user logs in I'd like to direct them to the first unanswered question, in this case 2. Once the second question is answered the user would be redirected to the next unanswered question.
Any suggestions please?
#Dog, I think this offers the functionality you are looking for.
Tip: See this answer for information on downloading Microsoft's authoritative WSH reference as a Windows help file.
Option Explicit
Dim oQsm : Set oQsm = New QuestionStatusManager
With oQsm
.NumberOfQuestions = 10
.RestoreStatus("1,4,6")
.MarkQuestionAnswered(2)
WScript.Echo "Questions " & .ToString() & " have been answered."
WScript.Echo "Next unanswered question is: " & .GetNextUnansweredQuestion()
End With
Set oQsm = Nothing
' ------------------------------------------------------------------------
Class QuestionStatusManager
Private m_nNumberOfQuestions
Private m_aQuestionList()
Sub Class_Initialize()
m_nNumberOfQuestions = -1
End Sub
Sub Class_Terminate()
Erase m_aQuestionList
End Sub
Public Property Let NumberOfQuestions(n)
Dim bValid : bValid = False
If IsNumeric(n) Then
If n = CInt(n) Then
bValid = True
End If
End If
If Not bValid Then
Err.Raise vbObjectError + 1, "", _
"Value '" & n & "' is not an integer."
End If
m_nNumberOfQuestions = CInt(n)
ReDim m_aQuestionList(n)
End Property
Public Property Get NumberOfQuestions()
CheckState
NumberOfQuestions = m_nNumberOfQuestions
End Property
Private Sub CheckState()
If m_nNumberOfQuestions = -1 Then
Err.Raise vbObjectError + 1, "", _
"Property 'NumberOfQuestions' has not been set."
End If
End Sub
Sub RestoreStatus(sAlreadyAnswered)
CheckState
Dim aAlreadyAnswered : aAlreadyAnswered = Split(sAlreadyAnswered, ",")
Dim i
For i = 0 To UBound(m_aQuestionList)
m_aQuestionList(i) = False
Next
For i = 0 To UBound(aAlreadyAnswered)
m_aQuestionList(CInt(aAlreadyAnswered(i))) = True
Next
End Sub
Sub MarkQuestionAnswered(n)
Dim sDesc
CheckState
On Error Resume Next
m_aQuestionList(n) = True
If Err Or n = 0 Then
sDesc = Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1, "", _
"Can't mark question number '" & n & "' as answered: " & sDesc
End If
End Sub
Function GetNextUnansweredQuestion()
CheckState
Dim i
For i = 1 To UBound(m_aQuestionList)
If Not m_aQuestionList(i) Then
GetNextUnansweredQuestion = i
Exit Function
End If
Next
GetNextUnansweredQuestion = -1
End Function
Function ToString()
CheckState
Dim sDelim : sDelim = ""
Dim i
ToString = ""
For i = 1 To UBound(m_aQuestionList)
If m_aQuestionList(i) Then
ToString = ToString & sDelim & CStr(i)
sDelim = ","
End If
Next
End Function
End Class
Related
This code basically takes a mathematical expression and evaluates it.
The following code i have written in VB.net shamelessly taken from here : Expression Evaluation
which has been written in Java.
Public Function evaluate(expression As [String]) As Integer
Dim tokens As Char() = expression.ToCharArray()
' Stack for numbers: 'values'
Dim values As New Stack(Of UInteger)()
' Stack for Operators: 'ops'
Dim ops As New Stack(Of Char)()
For i As Integer = 0 To tokens.Length - 1
' Current token is a whitespace, skip it
If tokens(i) = " "c Then
Continue For
End If
' Current token is a number, push it to stack for numbers
If tokens(i) >= "0"c AndAlso tokens(i) <= "9"c Then
Dim sbuf As New StringBuilder(100)
'Dim sbuf As New String("", 128)
' There may be more than one digits in number
If i < tokens.Length AndAlso tokens(i) >= "0"c AndAlso tokens(i) <= "9"c Then
sbuf.Append(tokens(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)))
End If
If sbuf Is Nothing AndAlso sbuf.ToString().Equals("") Then
Else
Dim intgr As Integer
Dim accpt As Boolean = Integer.TryParse(sbuf.ToString(), intgr)
If accpt = True Then
values.Push([Integer].Parse(sbuf.ToString()))
Else
Dim space As String = " "
values.Push(space)
End If
End If
' Current token is an opening brace, push it to 'ops'
ElseIf tokens(i) = "("c Then
ops.Push(tokens(i))
' Closing brace encountered, solve entire brace
ElseIf tokens(i) = ")"c Then
While ops.Peek() <> "("c
values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
End While
ops.Pop()
' Current token is an operator.
ElseIf tokens(i) = "+"c OrElse tokens(i) = "-"c OrElse tokens(i) = "*"c OrElse tokens(i) = "/"c Then
' While top of 'ops' has same or greater precedence to current
' token, which is an operator. Apply operator on top of 'ops'
' to top two elements in values stack
While Not ops.Count = 0 AndAlso hasPrecedence(tokens(i), ops.Peek())
values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
End While
' Push current token to 'ops'.
ops.Push(tokens(i))
End If
Next
' Entire expression has been parsed at this point, apply remaining
' ops to remaining values
While Not ops.Count = 0
values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
End While
' Top of 'values' contains result, return it
Return values.Pop()
End Function
Public Function hasPrecedence(op1 As Char, op2 As Char) As [Boolean]
If op2 = "("c OrElse op2 = ")"c Then
Return False
End If
If (op1 = "*"c OrElse op1 = "/"c) AndAlso (op2 = "+"c OrElse op2 = "-"c) Then
Return False
Else
Return True
End If
End Function
' A utility method to apply an operator 'op' on operands 'a'
' and 'b'. Return the result.
Public Function applyOp(op As Char, b As Integer, a As Integer) As Integer
Select Case op
Case "+"c
Return a + b
Case "-"c
Return a - b
Case "*"c
Return a * b
Case "/"c
If b = 0 Then
'Throw New UnsupportedOperationException("Cannot divide by zero")
End If
Return a \ b
End Select
Return 0
End Function
this is how im using the code :
formula = "10 + 2 * 6"
Dim result As Double = evaluate(formula)
and i keep getting this following error:
Unhandled exception at line 885, column 13 in http:**** DEDOM5KzzVKtsL1tWZwgsquruscgqkpS5bZnMu2kotJDD8R38OukKT4TyG0z97U1A8ZC8o0wLOdVNYqHqQLlZ9egcY6AKpKRjQWMa4aBQG1Hz8t_HRmdQ39BUIKoCWPik5bv4Ej6LauiiQptjuzBMLowwYrLGpq6dAhVvZcB-4b-mV24vCqXJ3jbeKi0&t=6119e399
0x800a139e - Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Conversion from string " " to type 'UInteger' is not valid.
Im a beginner but i think that the error is occurring because its not able to covert space into integer.How to deal with the spaces??
Any help is much appreciated:).
VB.NET is strongly-typed, so you simply cannot push anything other than integers onto a Stack(Of Integer). Therefore this code:
Dim space As String = " "
values.Push(space)
will always fail at runtime. (By the way, you want to set Option Explicit On and Option Strict On at the top of every module. If you do that, the line above will already be marked as an error at build time).
I haven't tried executing your code, but why would you need to save the spaces if what you're building is an expression evaluator? It doesn't seem to add anything to the evaluation. Perhaps if you simply don't add the spaces to the stack it will work anyway.
I have a recursive function that creates a list of items based on their hierarchy(integer is used to determine which level 1 to 10 max). There can be x number of items in any given level. I want to store all the items that belong the same level at the corresponding index of the jagged array. The items aren't retrieved based on their level so the level can be jumping around all of over the place as the function recurses.
Function RecurseParts(lngPartID1, lngLevel) As Object
'this function will recursivley print the parts lists for the part ID passed in
If IsNumeric(lngPartID1 & "") Then
Dim objRSTemp As Object = Server.CreateObject("ADODB.Recordset")
objRSTemp.CursorLocation = adUseClient
objRSTemp.Open(PART_LIST_SQL & lngPartID1, objConn, adOpenForwardOnly, adLockReadOnly)
'objRSTemp.ActiveConnection = Nothing
If objRSTemp.eof And objRSTemp.bof Then
'PROBLEM, WE HAVE NO RECORDS
Response.Write("There Were No Parts For This Assembly (Part ID #:" & lngPartID1 & ")")
Else
'make output
Dim strTemp As String = String.Empty
If lngLevel <> 1 Then strTemp = " style=""display: none;"">"
Response.Write("<table id='tblparts" & lngCurrentLineNum & "' border=""0"" cellspacing=""0"" width=""100%"" cellpadding=""1"" " & strTemp)
Do Until objRSTemp.EOF
'increase the current line num
lngCurrentLineNum = lngCurrentLineNum + 1
'get current Part ID
lngCurrentPartID = objRSTemp("PartID").value
'reset flag
blnIsAssm = False
'loop thru array of assemblies to see if this is a parent
For ctr = 0 To UBound(arrAssmList, 2)
If arrAssmList(0, ctr) = lngCurrentPartID Then
'the current part is an assembly
blnIsAssm = True
Exit For
ElseIf arrAssmList(0, ctr) > lngCurrentPartID Then
Exit For
End If
Next
If blnIsAssm Then
'recurse these parts
If RecurseParts(objRSTemp("PartID").value, lngLevel + 1) = True Then
'awesome
End If
End If
objRSTemp.MoveNext()
Loop
Response.Write("</table>")
End If
If objRSTemp.State Then objRSTemp.Close()
objRSTemp = Nothing
'RETURN FUNCTION
RecurseParts = True
Else
'no PART ID passed in
Response.Write("No Part ID Passed In")
RecurseParts = False
End If
End Function
It sounds like a Dictionary would work here.
Dim myDict As New Dictionary(Of Integer, List(Of String))
In your recursive function. The parts in the {} are the parts you have to supply.
'this builds the keys as you go
If Not myDict.ContainsKey({{key} -> your Integer}) Then
'add key and use the From statement to add a value if know at this time
myDict.Add({key}, New List(Of String) From {value})
Else
myDict({key}).Add({string to insert at this level})
End If
List of keys in reverse order:
Dim keys = myDict.Keys.OrderByDescending(Function(k) k)
I was able to create a List to store all the partIDs and their levels.
Dim arrSubID As New List(Of List(Of Integer))()
Function RecurseParts(paramenters)
For ctr = 0 To UBound(arrAssmList, 2)
If arrAssmList(0, ctr) = lngCurrentPartID Then
'checks whether we need a new index in the list
If lngLevel + 1 > arrSubID.Count Then
arrSubID.Add(New List(Of Integer))
End If
'adds the partID where it belongs!
arrSubID(lngLevel).Add(lngCurrentPartID)
blnIsAssm = True
Exit For
ElseIf arrAssmList(0, ctr) > lngCurrentPartID Then
Exit For
End If
Next
End Function
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles submit.Click
If (txtuid.Text = "isol" & txtpwd = "a") Then
Session("uid") = txtuid.Text
Response.Redirect("IPDbilling.aspx")
Return
Else
lblmsg.text = "invalide details"
lblmsg.ForeColor = System.Drawing.Color.Red
Response.Redirect("login.aspx")
End If
End Sub
Try using And instead of &.
If (txtuid.Text = "isol" And txtpwd = "a") Then
Also, if txtpwd is a TextBox, you need to use txtpwd.Text, not txtpwd.
& in VB.NET is a concatenation operator for strings:
Dim val1 As String = "Hello"
Dim val2 As String = " World!"
Dim val3 As String = val1 & val2
val3 will equal "Hello World!"
You can also use AndAlso to perform short-circuit evaluation:
If (txtuid.Text = "isol" AndAlso txtpwd = "a") Then
In this case, if txtuid.Text is not equal to "isol" the second part (txtpwd = "a") will not be evaluated, because the first part already failed (was false).
From what I see you have a compilation error and a logical one
compilation:
& should be replaced with AND I'm guessing you're a c#/cpp/c person.
Logic:
there is no need to Return after Response.Redirect, only one exit
there is a catch, you can use Response.Redirect(locationString,True)
that will delay the redirect until you are out of the sub, I dont like it as there is no reason to delay if you control the flow anyway.
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles submit.Click
Dim whereToNext As String
If (txtuid.Text = "isol" AND txtpwd.Text = "a") Then
Session("uid") = txtuid.Text
whereToNext = "IPDbilling.aspx"
Else
lblmsg.Text = "invalide details"
lblmsg.ForeColor = System.Drawing.Color.Red
whereToNext = "login.aspx"
End If
Response.Redirect(whereToNext)
End Sub
I hope this helps
M
p.s.
when leaving the sub with Response.Redirect will throw a ThreadCancelledException that you can just shrug off. It is thrown because you left the sub in a non clean way.
If you want to leave cleanly use the Response.Redirect(string,True) but use it at the end of your Sub.
Is there any way to list available methods for created object in VBS?
For example:
Set IE = CreateObject("InternetExplorer.Application")
I want to list available properties of this object, as:
IE.AddressBar
IE.Application
IE.Busy
...
or methods:
IE.ClientToWindow
IE.ExecWB
IE.GetProperty
...
How can I discover available properties to arbitrary valid object in VBS?
Using TypeLib Information Objects from tlbinf32.dll it is possible to list all members of a class.
`tlbinf32.dll` was part of *Visual Studio 6.0*, which was the current release in the years around 2000. Microsoft seems to not offer the DLL for download anymore (situation mid 2017), but you can download it from various sites on the internet. I found version *1.1.88.4, Build 8804, Copyright Matthew Curland 1996, Microsoft 1997-2000, size 148.480 Bytes* at https://www.dll4free.com/tlbinf32.dll.html, or other sites.
To install the DLL in Win32, copy it to `%windir%\System32` and *as administrator* call `regsvr32.exe tlbinf32.dll` from that directory.
To insttall the DLL in Win64, copy it to `%windir%\syswow64`, then *as administrator* register with `%windir%\syswow64\regsvr32.exe`, and finally run the vbscript with `%windir%\syswow64\cscript.exe` (or `wscript.exe`). Thanks [BuvinJ](/users/3220983/buvinj) for the [hint](/questions/14305750/list-object-methods-and-properties/44459670?noredirect=1#comment86169321_44459670)
The following script demonstrates the included function VariableInfo which will return a string with the type of the passed variable, and in case of an Object, all members with details, including type of Property, callable type (Sub or Function), and parameter names and return type in case of Function. The type name of the object in case of a COM object would be the name of the implemented Interface. Not sure if it works for multiple implemented interfaces, but AFAIK it's not possible to implement multiple interfaces in one class via COM anyway.
It does not support recursion in any way, because this would lead to infinity loops for some types.
This will give you virtually full working reflection in VBS. Great to explore APIs for example with the Microsoft Script Debugger.
' Reflection for VBScript via tlbinfo32.dll
'
' Patrick Strasser-Mikhail 2017-2021
' Ansgar Wiechers 2019
' https://stackoverflow.com/questions/14305750/list-object-methods-and-properties/44459670#44459670
'
' v1.1 2021-02-01: Show values of arrays and objects, but only one level
' Returns a String describing the passed object/variable on the first level,
' no recursion.
Function VariableInfo(obj)
VariableInfo = VariableInfoToLevel(obj, 0, 1)
End Function
' Returns a String describing the passed object/variable on the first level,
' recurse down to level max_level(0=no recursion).
Function VariableInfoToLevel(obj, level, max_level)
Const invokeKindPropertyGet = 0 ' simple data member
Const invokeKindFunction = 1 ' method: Sub or Function
Const invokeKindPropertyPut = 2 ' Docs: has a value setter; reality: more like is settable
Const invokeKindPropertyPutRef = 4 ' Docs: has a reference setter; reality: more like is not settable
If level > max_level Then
VariableInfoToLevel = ""
Exit Function
End If
Dim indent : indent = Space(4 * level)
VariableInfoToLevel = indent
If isEmpty(obj) Or _
isNull(obj) _
Then
VariableInfoToLevel = VariableInfoToLevel & TypeNameFromVarType(VarType(obj))
ElseIf Not IsObject(obj) Then
If Not isArray(obj) Then
VariableInfoToLevel = indent & TypeNameFromVarType(VarType(obj)) & ", Value: [" & obj & "]"
Else
VariableInfoToLevel = indent & TypeNameFromVarType(VarType(obj))
Dim dimension
ReDim sizes(0)
Dim size
On Error Resume Next
Err.Clear
For dimension = 0 To 10 ' deliberate limit to prevent infinite loop
size = Ubound(obj, dimension + 1)
If Err.Number <> 0 Then
' report ther then Index out of Bounds
If Err.Number <> 9 Then
WScript.Echo "Exception " & Err.Number & ": " & Err.Description & "; in " & Err.Source
End If
Exit For
End If
ReDim Preserve sizes(dimension)
sizes(dimension) = size
Next
On Error Goto 0
VariableInfoToLevel = VariableInfoToLevel & "(" & Join(sizes, ",") & ")"
Select Case dimension
Case 1
VariableInfoToLevel = VariableInfoToLevel & " {" & vbCrlf
Dim idx
For idx = LBound(obj) To UBound(obj)
VariableInfoToLevel = VariableInfoToLevel & indent & _
" " & idx & ":" & _
Trim(VariableInfoToLevel(obj(idx), level + 1, max_level)) & vbCrlf
Next
VariableInfoToLevel = VariableInfoToLevel & indent & "}" & vbCrlf
Case 2
VariableInfoToLevel = indent & "{" & vbCrlf
Dim idx1, idx2
For idx1 = LBound(obj, 1) To UBound(obj, 1)
For idx2 = LBound(obj, 2) To UBound(obj, 2)
VariableInfoToLevel = VariableInfoToLevel & indent & _
" " & idx1 & "," & idx2 & ":" & _
Trim(VariableInfoToLevel(obj(idx1, idx2), level + 1, max_level)) & vbCrlf
Next
Next
VariableInfoToLevel = VariableInfoToLevel & indent & " }" & vbCrlf
Case Else
' 0 is empty anyway, more is too complicated to print, just leave it for now
End Select
End If
ElseIf TypeName(obj) = "Nothing" Then
VariableInfoToLevel = indent & "Nothing (The Invalid Object)"
Else
' Object
VariableInfoToLevel = indent & "Object " & TypeName(obj)
'' Need to think about that... True for Err, but not for System.Dictionary
'' Seems Err is very special, and we should compare explicitly with internal/predifined Objects (Err, WScript)
'If varType(obj) <> vbObject Then
' hm, interresting...
' VariableInfoToLevel = VariableInfoToLevel & " with default property (no analysis possible)"
' Exit Function
'End If
Dim TLI
Dim MemberInfo
Dim TypeInfo
Set TLI = CreateObject("TLI.TLIApplication")
VariableInfoToLevel = indent & "Object " & TypeName(obj)
On Error Resume Next
Err.Clear
Set TypeInfo = TLI.InterfaceInfoFromObject(obj)
If Err.Number <> 0 Then
VariableInfoToLevel = VariableInfoToLevel & "; Error " & Err.Number
VariableInfoToLevel = VariableInfoToLevel & ": " & Err.Description
Err.Clear
On Error Goto 0
Exit Function
End If
On Error Goto 0
For Each MemberInfo In TypeInfo.Members
Dim Desc
Dim printNextLevel : printNextLevel = vbFalse
Desc = ""
' based on .Net System.Runtime.IteropService.ComTypes
'' FIXME: Call by Value/Reference and settable seems to be switched some
'' InvokeKind seems to not encode value passing, rather settable/not settable
'' Needs more work to decode byValue/byReference
Select Case MemberInfo.InvokeKind
Case InvokeKindFunction
If MemberInfo.ReturnType.VarType <> 24 Then
Desc = " Function " & TypeNameFromVarType(MemberInfo.ReturnType.VarType)
Else
Desc = " Sub"
End If
Desc = Desc & " " & MemberInfo.Name
Dim ParameterList
ParameterList = Array()
Dim Parameter
For Each Parameter In MemberInfo.Parameters
ReDim Preserve parameterList(UBound(ParameterList) + 1)
ParameterList(Ubound(parameterList)) = Parameter.Name
Next
Desc = Desc & "(" & Join(ParameterList, ", ") & ")"
'Set parameters = Nothing
Case InvokeKindPropertyGet
Desc = " Data Member " & MemberInfo.Name
printNextLevel = vbTrue
Case InvokeKindPropertyPut
' Seems to be
Desc = " Property " & MemberInfo.Name & " [set by val"
If IsGettable(obj, MemberInfo.Name) Then
Desc = Desc & "/get"
printNextLevel = vbTrue
End If
Desc = Desc & "]"
'Stop
Case InvokeKindPropertyPutRef
'Stop
Desc = " Property " & MemberInfo.Name & " [set by ref"
If IsGettable(obj, MemberInfo.Name) Then
Desc = Desc & "/get"
printNextLevel = vbTrue
End If
Desc = Desc & "]"
'Stop
Case Else
Desc = " Unknown member, InvokeKind " & MemberInfo.InvokeKind
End Select
VariableInfoToLevel = VariableInfoToLevel & vbNewLine & _
indent & Desc
If printNextLevel And level < max_level Then
VariableInfoToLevel = VariableInfoToLevel & vbNewLine & _
VariableInfoToLevel(eval("obj." & MemberInfo.Name), level + 1, max_level)
End If
Next
Set TypeInfo = Nothing
Set TLI = Nothing
End If
End Function
Function IsGettable(obj, memberName)
Dim value
On Error Resume Next
Err.Clear
value = eval("obj." & memberName)
Stop
If Err.Number <> 0 And _
Err.Number <> 438 And _
Err.Number <> 450 Then
WScript.Echo Err.Number & ": " & Err.Description
End If
'438: Object doesn't support this property or method
'450: Wrong number of arguments or invalid property assignment
If Err.Number = 438 Or _
Err.Number = 450 Then
IsGettable = vbFalse
Else
IsGettable = vbTrue
End If
End Function
Function IsSimpleType(obj)
If (isEmpty(obj) Or isNull(obj)) And (Not IsObject(obj)) And (Not isArray(obj)) Then
IsSimpleType = vbTrue
Else
IsSimpleType = vbFalse
End If
End Function
' Decode Type Number to something readable
Function TypeNameFromVarType(typeNr)
Dim typeDetails
set typeDetails = CreateObject("Scripting.Dictionary")
typeDetails.add 0, "vbEmpty (uninitialized variable)"
typeDetails.add 1, "vbNull (value unknown)"
typeDetails.add 2, "vbInteger" ' Short?
typeDetails.add 3, "vbLong" ' Integer?
typeDetails.add 4, "vbSingle"
typeDetails.add 5, "vbDouble"
typeDetails.add 6, "vbCurrency"
typeDetails.add 7, "vbDate"
typeDetails.add 8, "vbString"
typeDetails.add 9, "vbObject"
typeDetails.add 10, "Exception"
typeDetails.add 11, "vbBoolean"
typeDetails.add 12, "vbVariant"
typeDetails.add 13, "DataObject"
typeDetails.add 14, "vbDecimal"
typeDetails.add 17, "vbByte"
typeDetails.add 18, "vbChar"
typeDetails.add 19, "ULong"
typeDetails.add 20, "Long" ' realy Long?
typeDetails.add 24, "(void)"
typeDetails.add 36, "UserDefinedType"
If typeDetails.Exists(typeNr) Then
TypeNameFromVarType = typeDetails(typeNr)
ElseIf typeNr > 8192 Then
TypeNameFromVarType = "vbArray{" & TypeNameFromVarType(typeNr - 8192) & "}"
Else
typeNameFromVarType = "Unknown Type " & typeNr
End If
End Function
' Some nice example class to demonstrate all possible interfaces.
Class MyClass
Dim Name_
Dim Name2_
Dim Name3_
Dim Name4_
Dim dict
Private Sub Class_Initialize()
Name_ = "foo"
Name2_ = "bar"
Name3_ = "baz"
Name4_ = "spam"
Set dict = CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate()
Set dict = Nothing
End Sub
Public Property Get Name
Name = Name_
End Property
Public Property Let Name(ByVal Value)
Name_ = Value
End Property
Public Property Let Name2(ByRef Value)
Set Name2_ = Value
End Property
Public Property Get Name3
Name3 = Name3_
End Property
Public Property Set Name3(ByVal Value)
Set Name3_ = Value
End Property
Public Property Get Name4
Name4 = Name4_
End Property
Public Property Set Name4(ByRef Value)
Set Name4_ = Value
End Property
Sub TestSub()
WScript.Echo "Test"
End Sub
Sub TestFunc(message)
WScript.Echo "Test: " & message
End Sub
Sub TestFunc2(ByRef message)
WScript.Echo "Test: " & message
End Sub
Function Add(first, second)
Add = first + second
End Function
Function Substract(ByVal first, ByRef second)
Add = first - second
End Function
End Class
Sub testVariableInfo()
Dim variable
' vbEmpty
Wscript.Echo VariableInfo(variable)
variable = Null
Wscript.Echo VariableInfo(variable)
Set variable = Nothing
Wscript.Echo VariableInfo(variable)
Wscript.Echo VariableInfo(Int(23))
Wscript.Echo VariableInfo(cLng(23))
Wscript.Echo VariableInfo(2147483647)
Wscript.Echo VariableInfo(5/4)
Wscript.Echo VariableInfo(4 * Atn(1)) ' Simplest way to pi, not all inverse functions like arcsin are defined.
Wscript.Echo VariableInfo(3.4E38)
Wscript.Echo VariableInfo(CDbl(3.4E38))
Wscript.Echo VariableInfo(cCur(20.123456))
Wscript.Echo VariableInfo(now)
Wscript.Echo VariableInfo("Some Text")
Wscript.Echo VariableInfo(Err)
Dim MyObject
Set MyObject = new MyClass
Wscript.Echo VariableInfo(MyObject)
Set MyObject = Nothing
Dim TestAEmpty()
Wscript.Echo VariableInfo(TestAEmpty)
ReDim TestA1(17)
Wscript.Echo VariableInfo(TestA1)
Dim TestA2(3, 7)
Wscript.Echo VariableInfo(TestA2)
Dim TestA3
TestA3 = Array(4, 5, 6)
Wscript.Echo VariableInfo(TestA3)
Dim dict
Set dict = CreateObject("Scripting.Dictionary")
WScript.Echo VariableInfo(dict)
Set dict = Nothing
End Sub
testVariableInfo
For for more information about the Typelib Interface, get the documentation help file from Microsoft KB artivle 224331
Matthew Curland offers for download at the website to his book Advanced Visual Basic 6 the nice program Type Library Editor (EditTLBEval.exe) as evaluation version, and the according Documentation
Especially in this context I really like the line If you're a Visual Basic developer who refuses to recognize the commonly accepted limitations of VB, this book is definitely for you. by Ted Pattison. Just replace VB by VBScript here.
VBWebProfi gave the hint for TLI, thanks for that. Working out the details and writing the code was several hours of work, though ;-)
VBScript itself does not support type introspection outside the TypeName and VarType functions, which will give you the type of an object, but won't give you access to its internal structure.
As other answers explained there is a DLL that would provide this feature, but it doesn't ship with Windows, and since it was part of an old version of Visual Studio there might not be a legal way to obtain it nowadays.
While that is partially true, its incomplete.... Google, GetObjectText_, Methods_, & Propeties_
The referenced methods will only work on objects collected while connected to the cimv2 namespace of a remote host via the WbemScripting.SWbemLocator object. If this object has the ability to work on localhost, it's unapparent to me.
Once you do this you can query any of the classes held therein [Win32_Services,Win32_Drives, etc] and interrogate the objects in the resultset using a For-Next loop on the object like below...
For Each oProp in oObject.Properties_
'be careful here because some propeties may be an object or an array.
'so test for that here using "typename" or "vartype"
wScript.Echo oProp.Name & vbTab & oProp
Next
Or...
For Each oMethod in oObject.Methods_
wScript.Echo oProp.Name
Next
Finally, ...
For Each oProp in oObject.Properties_
'This will display all of an objects properties
oProp.GetObjectText_
Next
If you happen to be using HP UFT or QTP then follow these steps:
1) Install any version of MS Visual Studio onto your laptop. (Don't worry about licensing, you won't be running VS)
2) Reboot your computer.
3) Launch UFT or QTP, load a script and hit F11, (or pause at any piece of code that is near the object you want to inspect).
4) Add the object to the Watch window. It can be an Object Repository object or a programmatic description.
If the object exists, the object will now display two Plus (+) signs in the Watch window that can be expanded to show all available Methods and Properties, as well as child objects that can be expanded.
Use TLI . The TLI.TLIApplication class (from tlbinf32.dll) can inspect various COM objects from their instance. Explore the TLI library in Excel or other Microsoft product that supports scripting and has an script editor which is able to add references, then add tlbinf32.dll. The name in the references is "Typelib information".
Note that the DLL does not ship with Windows, though.
Use the method InterfaceInfoFromObject() for VBScript classes and alternatively try ClassInfoFromObject().
Option Explicit
Dim TLI
Dim MyObject
Dim TypeInfo
Dim MemberInfo
Set TLI = CreateObject("TLI.TLIApplication")
Set MyObject = New MyClass
Set TypeInfo = TLI.InterfaceInfoFromObject(MyObject)
For Each MemberInfo In TypeInfo.Members
WScript.Echo MemberInfo.Name
Next
Class MyClass
Dim Name_
Public Property Get Name
Name = Name_
End Property
Public Property Let Name(ByVal Value)
Name_ = Value
End Property
End Class
Try this ...
For i = 0 To webElementCount-1 Step 1
innertextProp = myValue2(i).GetROProperty("innertext")
print i & innertextProp
print innertextProp
Next
This title of the question may seem to be previously asked and answered but its different scenario for me. I use this script to stop sql injection in my ASP site. As per my knowledge or injecting script i have tried everything . Is it still possible to break through this code or do you feel this is fine .
Here is the script
<%
Function IsInject(strCheck, boolForm)
IsInject = False
If Not boolForm And Len(strCheck) > 50 Then IsInject = True
' Dim sCmdList, arrCmds, i
If boolForm Then
sCmdList = "declare,varchar,convert,delete,create,is_srvrolemember,ar(,cast("
Else
sCmdList = "update,union,select,drop,declare,varchar,convert,delete,create,is_srvrolemember,ar(,cast(,char("
End If
arrCmds = Split(sCmdList, ",")
For i = 0 To UBound(arrCmds)
If Instr(UCase(CStr(strCheck)), UCase(arrCmds(i))) > 0 Then
IsInject = True
Exit For
End If
Next
Erase arrCmds
End Function
Function CleanInject(strClean, boolInt)
If boolInt Then CleanInject = CInt(strClean) Else CleanInject = Replace(strClean, "'", "''")
End Function
'-----------------------------------------------------------
'redirect user if specific IP
'Dim ipaddress, bFBIRedirect, sInjectType
bFBIRedirect = True
ipaddress = Request.ServerVariables("REMOTE_ADDR")
Select Case ipaddress
Case "90.120.206.10"
Case Else
bFBIRedirect = False
End Select
If bFBIRedirect Then Response.Redirect "http://www.fbi.gov"
'-----------------------------------------------------------
'Dim bIsInject, sHackString
bIsInject = False
If Not bInject Then
' Dim qsItm
For Each qsItm In Request.QueryString
If IsInject(Request.QueryString(qsItm), False) Then
bIsInject = True
sHackString = qsItm & "=" & Request.QueryString(qsItm)
sHackType = "QueryString"
sInjectType = "qs-" & Request.QueryString(qsItm)
Exit For
End If
Next
End If
If Not bInject Then
' Dim frmItm
' For Each frmItm In Request.Form
' If IsInject(Request.Form(frmItm), True) Then
' bIsInject = True
' sHackString = Request.Form(frmItm)
' sHackString = frmItm & "=" & Request.Form(frmItm)
' sHackType = "Form"
' Exit For
' End If
' Next
End If
If bIsInject Then
Session("hacktype") = sHackType
Session("hackstr") = sHackString
Session("thepagefrom") = Request.ServerVariables("PATH_INFO")
Session("theip") = Request.ServerVariables("REMOTE_ADDR")
' Dim arrWhereAt, iWhereAt, sRedirect
arrWhereAt = Split(Request.ServerVariables("PATH_INFO"), "/")
iWhereAt = UBound(arrWhereAt)
sRedirect = "unknownerror.asp?ip=" & Request.ServerVariables("REMOTE_ADDR") & "&err=" & sInjectType & "&pg=" & Request.ServerVariables("PATH_INFO")
If iWhereAt = 1 Then sRedirect = "../" & sRedirect
If iWhereAt = 2 Then sRedirect = "../../" & sRedirect
If iWhereAt = 3 Then sRedirect = "../../../" & sRedirect
Response.Redirect sRedirect
End If
%>
Using blacklists to remove commands is not really a good idea. You have to make sure you cover all possible commands, and still someone might sneak something past. This would also probably fail if you get data from a user that is not an attack, but still contains an attack string. Example "Back in the days of the Soviet Union".
As Nikolai suggests, see if you can find some type of prepared statements to use. Or find a really good library to properly escape data for you.
rather doing that I think I would use ADO Parameter object when creating SQL queries, the second best thing is to do type conversion of the inputfields for the dynamic SQL queries, such as converting strings to SQL strings (replace any ' with two ''), making sure number is a number etc.