Please see below function fnWaitCheckFinalStatus if Else part is executed in below code then value return by Function fnWaitCheckFinalStatus is coming blank because function this is called recursively fnWaitCheckFinalStatus.
Is there way to get return value of fnWaitCheckFinalStatus After exit function function should exit all its state.
How can I make it possible , any pointers on this.
Function fnWaitCheckFinalStatus(objStatusBar)
Dim blnRetValue : blnRetValue = True
Dim i : i=0
If objStatusBar.Exist Then
strValue=ObjStatusBar.GetROProperty("text")
Do
wait 10
strValue=ObjStatusBar.GetROProperty("text")
Loop While strValue = "Task Started"
End If
strValue1=ObjStatusBar.GetROProperty("text")
If strValue1="Task executed successfully" Then
blnRetValue1=True
fnWaitCheckFinalStatus = blnRetValue1
Exit Function
ElseIf strValue1="Task execution failed" Then
blnRetValue1=False
fnWaitCheckFinalStatus = blnRetValue1
Exit Function
Else
Call fnWaitCheckFinalStatus(objStatusBar)
End If
End Function
Consider "pass-through"ing the function result if you return from the recursion, like in this code (note the line with the !!! comment):
Function fnWaitCheckFinalStatus(objStatusBar)
Dim i : i=0
If objStatusBar.Exist Then
strValue=ObjStatusBar.GetROProperty("text")
Do
wait 10
strValue=ObjStatusBar.GetROProperty("text")
Loop While strValue = "Task Started"
End If
strValue1=ObjStatusBar.GetROProperty("text")
If strValue1="Task executed successfully" Then
fnWaitCheckFinalStatus = true
ElseIf strValue1="Task execution failed" Then
fnWaitCheckFinalStatus = false
Else
fnWaitCheckFinalStatus=fnWaitCheckFinalStatus(objStatusBar) ' !!!
End If
End Function
Also, I eliminated the result buffer variable. You donĀ“t need it, so you can scratch it.
Also, I'd avoid exit function in this case to keep the code simpler (one entry point, one exit point), so I eliminated that, too.
Generally speaking, there is no obvious reason for using recursion here since you pass exactly the same argument as you receive, so the recursive call will do exactly the same as its caller scope. Use a loop instead.
Related
How would you exit out of a function if a condition is true without killing the whole script, just return back to before you called the function.
Example
# Start script
Do scripty stuff here
Ok now lets call FUNCT
FUNCT
Here is A to come back to
function FUNCT {
if [ blah is false ]; then
exit the function and go up to A
else
keep running the function
fi
}
Use:
return [n]
From help return
return: return [n]
Return from a shell function.
Causes a function or sourced script to exit with the return value
specified by N. If N is omitted, the return status is that of the
last command executed within the function or script.
Exit Status:
Returns N, or failure if the shell is not executing a function or script.
Use return operator:
function FUNCT {
if [ blah is false ]; then
return 1 # or return 0, or even you can omit the argument.
else
keep running the function
fi
}
If you want to return from an outer function with an error without exiting you can use this trick:
do-something-complex() {
# Using `return` here would only return from `fail`, not from `do-something-complex`.
# Using `exit` would close the entire shell.
# So we (ab)use a different feature. :)
fail() { : "${__fail_fast:?$1}"; }
nested-func() {
try-this || fail "This didn't work"
try-that || fail "That didn't work"
}
nested-func
}
Trying it out:
$ do-something-complex
try-this: command not found
bash: __fail_fast: This didn't work
This has the added benefit/drawback that you can optionally turn off this feature: __fail_fast=x do-something-complex.
Note that this causes the outermost function to return 1.
My use case is to run the function unless it's already running. I'm doing
mkdir /tmp/nice_exit || return 0
And then at the end of the function
rm -rf /tmp/nice_exit
I have two functions, and I am trying to use the result of one function in the second one. It's going to the else part, but it's not printing anything for "cus_number".
How do I get the "cus_number" printed?
Function getNumber
number = "423"
End Function
cus_number = getNumber
If (IsNull(cus_number)) Then
WScript.Echo "Number is null"
Else
WScript.Echo "cus_number : " & cus_number
End If
To return a value from a VBScript function, assign the value to the name of the function, like this:
Function getNumber
getNumber = "423"
End Function
I need to pass an object and its operation in a function so that each time I can call the function only and save me to write same steps for all the objects like validating the object before performing an operation. Similar way to a Register User Function in QTP/UFT.
However, Testcomplete doesn't have this feature (atleast under my knowledge, would be happy to know if there is)
This is my code that I am trying but unable to:
Call OpenPageorTab("Aliases.Admin.wndMain.toolStrip", ".Visible")
Function OpenPageorTab(obj, method)
'if obj.Exists then
execute a = obj&method
delay(1000)
OpenPageorTab = True
'Else
log.Error "Unable to find the object"
OpenPageorTab = False
'End if
using if condition as i was passing object earlier instead of string
It fails at "execute" statement and gives me VbScript runtime error when executing this statement.
my question is two fold -
How do I pass objects and its operation in a function and execute it
Also is it possible to pass an object it self instead of string for ex:
obtoolbar = "Aliases.Admin.wndMain.toolStrip"
Call OpenPageorTab(obtoolbar, ".Visible")
Appreciate any help or direction on this issue
EDIT 1
I am somewhere close to an answer however not accurately. I am able to pass the object as string - Check the code below
Call OpenPageorTab("Aliases.Admin.wndMain.toolStrip", ".Click")
Function OpenPageorTab(obj, method)
' if obj.Exists then
eobj = "" & obj & method
execute (eobj)
delay(1000)
OpenPageorTab = True
' Else
log.Error "Unable to find the object"
OpenPageorTab = False
' End if
End Function
However I still need to pass the object something like
Set oToolStrip = Aliases.Admin.wndMain.toolStrip
Call OpenPageorTab(oToolStrip, ".Click")
This is something that I'm unable to do.
EDIT 2
I have already got the answer to this problem and have posted the solution. That being said, is there any way that Function can be utilized as a method ?
Here an example of how to reference a function and pass parameteers to it, including objects.
Const forReading = 1, forWriting = 2, forAppending = 8, CreateFile = True
Set my_obj = CreateObject("Scripting.FileSystemObject").OpenTextFile("c:\temp\test.txt", forWriting, CreateFile)
Function my_function(my_obj, method, text)
command = "my_obj." & method & " """ & text & """"
ExecuteGlobal command
End Function
'make a reference to our function
Set proc = GetRef("my_function")
'and call it with parameters, the first being the method invoked
Call proc(my_obj, "WriteLine", "testing")
'cleanup'
my_obj.Close
Set my_obj = Nothing
I was able to finally formulate the solution the below function can work as makeshift register function in TestComplete
Sub test
'Set the Object
Set pToolStrip = Aliases.Admin.wndMain.toolStrip.Button("User Admin")
Call GenericOperationFunc(pToolStrip, ".Click", "N")
'if you want to perform an operation which return a value
b = GenericOperationFunc(Aliases.Admin.wndPopup.Child(2), ".Caption", "Y")
End Sub
Public Function GenericOperationFunc(obj, method, Return)
GenericOperationFunc = False
on error resume next
if obj.Exists then
if Ret = "Y" then
eobj = "NewText="&"obj" & method
execute (eobj)
GenericOperationFunc = NewText
Delay(500)
Else
eobj = "obj" & method
execute (eobj)
delay(1000)
GenericOperationFunc = True
End if
Else
log.Error "Unable to find the object"
GenericOperationFunc = False
End if
End Function
'log.error, delay, aliases, ptoolstrip(object) are testcomplete specific
Is it possible in VBScript to determine the name of the function currently executing?
In .NET, you could do:
MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);
In the past, I build a callstack viewer to see the performance of each function that is called. This needs one extra line of VBS code per function/sub and some overhead during runtime of course because of the extra code.
bottom - up:
Function DoSomething(a, b, c)
dim registerFunctionObj : Set registerFunctionObj = [new RegisterFunction]("DoSomething")
' other code
End Function
Whenever the function is called, it creates a new instance of the RegisterFunction object. When the function exits, the registerFunctionObj variable goes out of scope automatically, calling the Class_Terminate sub of the instance.
[new RegisterFunction] is just a function that return a registerFunction instance:
Function [new RegisterFunction](funcName)
Set [new RegisterFunction] = new cls_RegisterFunction
[new RegisterFunction].FunctionName = funcName
Set [new RegisterFunction].CallStackViewer = CallStackViewer
End function
Class cls_RegisterFunction
Private functionName_, startTime_, callStackViewer_, endTime_
Private Sub Class_Initialize
startTime_ = now
callStackViewer_.LogInitialize me
End Sub
Public Property Let FunctionName(fName)
functionName_ = fName
End Property
Public Property Set CallStackViewer(byRef csv)
Set callStackViewer_ = csv
End Property
Private Sub Class_Terminate
endTime_ = now
callStackViewer_.LogTerminate me
End Sub
End Class
The CallStackViewer instance is a singleton instance of the a CallStackViewer class, but you can make it a part of your project, so you retrieve it through you global project class:
Private PRIV_callStackViewer
Public Function CallStackViewer()
If not IsObject(PRIV_callStackViewer) Then
Set PRIV_callStackViewer = new cls_CallStackViewer
End If
Set CallStackViewer = PRIV_callStackViewer
End Function
Class cls_CallStackViewer
Public Sub Class_Initialize
' Here you can retrieve all function libraries (as text file) extract the
' function name, the file they are in and the linenumber
' Put them in a dictionary or a custom object
End Sub
Public Sub LogInitialize(byref registerFunction)
' Here you can push the function on a stack (use a standard dotnet list>stack for it),
' log the starttime to a log object or handle custom breakpoints
End Sub
Public Sub LogTerminate(byref registerFunction)
' Here you can pop the function from a stack, log the endtime to a log
' object or handle custom breakpoints
End Sub
End Class
Disclaimer: The code in here is pure demo code created on the fly. It lacks functionality and is only here to explain the concept. It could contain errors and is not complete.
The only thing you need is one line of code per function and your own imagination to expand it.
No, but you can easily implement it
dim module_name
sub sub1
module_name = "sub1"
wscript.echo "i'm " & module_name
'do something
end sub
function function1
module_name = "function1"
wscript.echo "i'm " & module_name
function1 = "something"
end function
In case of recursion you could also remember the level you'r in so that you can get out if getting too deep.
I'm trying to write the VBScript equivalent of a function similar to what's below:
object getObject(str)
{
if ( ... )
{
return object_goes_here;
}
return null;
}
My guess would be below, except that I'm not understanding the difference between Nothing and Null. As a caller, I'd rather test if the return value is set by using IsNull() versus X Is Nothing.
Function getObject(str)
If ... Then
Set getObject = object_goes_here
Exit Function
End If
Set getObject = Nothing // <-- or should this be Null?
End Function
The correct way to not return an object is to return Nothing and test for Is Nothing.
VB's Null is a special value of type Variant/Null. There are other special values, such as Variant/Empty or Variant/Error. They all have their use, but it's not the one.
Use the second Function skeleton. Avoid Null when dealing with objects, because of the Set Assignment abomination.
Dim oX : Set oX = getObject(...)
If oX Is Nothing Then
...
Else
nice object to work with here
End If
vs
Dim vX : vX = getObject(...) ' <-- no Set, no object
If IsNull(vX) Then
...
Else
no object to work with here
End If
In your sample code, the object gets always Nothing because that is the last action. This is how it should be:
Function getObject(str)
If ... Then
Set getObject = object_goes_here
Exit Function
End If
Set getObject = Nothing
End Function
or:
Function getObject(str)
Set getObject = Nothing
If ... Then
Set getObject = object_goes_here
End If
End Function
The answer of GSerg is correct: you should use Nothing. Additionally, to see if an object has a null reference, use:
If Not object Is Nothing Then
' do something
End If