Removal of ByRef when creating using code causes a problem

Class library usage, coding and language questions.
KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Removal of ByRef when creating using code causes a problem

Post by KJG » Wed Jul 18, 2018 9:26 am

Hi All,

I have some older scripts from version 6 of Ranorex.
I have a repository item -
GenericListItem listitem[@text=$generallistvalue]

In my recordings I could call user code as follows: -
Usercode SetVariableTo() $generallistvale MyNewValue

The user code was defined as
Public Sub SetVariableTo(ByRef Variable As String, NewValue As String)
'
' Purpose:
' This sub will set the value of a variable passed in.
'
' Parameters:
' Variable The Variable to be set.
' NewValue The value to be assigned.
'
' Notes:
' This can be used to set Ranorex repository item variables and can avoid having to have
' many items in the repository.
'
' EXAMPLE
' To set the $MyItem variable value to "Execute"
' SetVariableTo( MyItem, "Execute")
'
' NOTE This may not work as a direct call but is usually used from the recording module where
' Variable should be set to the (green) variable and the new value entered as the NewValue parameter
'
'
Variable = NewValue
End Sub

And this used to work.

Now I have upgraded to Ranorex 7.1 and there are innumerable compilation errors referring to this sub. I discovered this is because I am using ByRef (which is a perfectly acceptable VB.NET clause).
If I take out the byref, the sub will compile but no longer do what I need it to do - change the value of the variable being passed in.

I no longer use this style of user code as I have split my recordings into much much smaller blocks and have a module which accepts the parameter and selects the correct list item, but it will take a long time to do this to this upgraded code.

Why has ByRef been removed since it is valid VB.NET and has been working? I really don't understand why this has been done. This simple removal is causing me pain on this project and I have several other projects using this style of code which I am updating. :x
Is there a quick way within my sub to use the same parameters to do what I need to do? If I can change the sub it will save having to change a lot of other scripts.

Regards,

Kevin

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Mon Jul 23, 2018 11:34 am

Hi Kevin,

"ByRef" was definitely not removed. I just tried your sub with Ranorex 8.2.0 and it compiled flawlessly.
VBTEst.png

I guess there is some other issue within your solution.

Cheers,
Robin
You do not have the required permissions to view the files attached to this post.

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Jul 31, 2018 2:54 pm

Thanks for your reply. I have only just got around to looking at this again.

I am now very confused.
I had working code which used ByRef as described before.
I have upgraded the project from Rx6 to Rx8.1 from Rx6.

The sub seems to have changed to a function
Public Function SetVariableTo(NewValue String) as String

And now the calls to this code are also changed to set the variable using this function. For example,
tasknametorun = SetVariableTo("Run MS Reporting Services Report Tool")

tasknametorun is the Repository variable.

So it seems that the upgrade process has changed the sub to a function so that it does nto need ByRef.

I wonder if this si true?
Anyway, after deleting one of the actual .vb code files from the project, this seems to have forced a rebuild of all the recordings and I have no compilation errors.

As a matter of interest, is there a way in a recording to set a repository variable value inline without user code?

Regards,

Kevin

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Fri Aug 03, 2018 11:25 am

Hi Kevin,

I'm glad that it works now.
As a matter of interest, is there a way in a recording to set a repository variable value inline without user code?
What exactly do you mean with "inline"?

Cheers,
Robin

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Aug 14, 2018 11:24 am

Ok, let me see if I can explain what I desire to do and then hopefully someone can tell me how foolish I am being and set me straight.

Let me deal with the specific case of a menu.
The menu is a generic list of items and I want to be able to select different items throughout a single test recording.
Suppose the menu is defined as
GenericListItem listitem[@text=$genericlistvalue]

In each recording where I wish to use my SetVariableTo sub, in the usercode.vb I would include the line
inherits genericusercode

Where genericusercode contains the SUB as defined in my earlier post (including the byref).

The recording would include a line such as
User Code SetVariableTo $genericlistvalue "First Menu Item"

After this, the repository item would point to the menu item I wanted to select so I could do just that -
Invoke action Select GenericListItem

Then in the recording, I could add another user code line and select the SetVariableTo sub.
I could then provide the same variable as the first parameter and the new value as the second parameter.
User Code SetVariableTo $genericlistvalue "Second Menu Item"

Then I can select on the same GenericListItem element but it would select the NEW ("Second menuItem") value for me.
Invoke action Select GenericListItem

After converting from Rx6 to Rx8 I can make this work, just about if I leave the converted SUB as a FUNCTION, BUT in the Recording, I cannot now use the variable as the first parameter as it is actually the output of the function
Public function SetVariableTo( NewValue As String) As String

used in (Ranorex Generated) code as
itemindex = SetVariableTo("1")

The "itemindex" used to be the first parameter of my call to the SUB but now the SUB has been converted to a function, I cannot set this "inline" in the recording. I cannot use this technique now as I would need to edit the Ranorex generated script to find all the lines where SetVariableTo FUNCTION is used and put the variable name in front and this code is not user editable anyway. In fact, this more or less makes the function redundant.

So I know I could break down all my (many) recordings to tiny modules so that every time I want to select a different menu Item I have to include a module and do the data mappings, but I wonder if there is an easier way from a central piece of GenericUserCode to set a repository variable.

It would be great if someone could tell me that I am missing the obvious method. Basically, I want a way to set a repository variable from within a recording from a static value such as a string. The actual variable name may also vary from one recording to another (sometimes it is a list index sometimes a menu text). Something like
Set Value RepositoryVariableName "myvalue"

Thanks in advance.

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Thu Aug 16, 2018 11:53 am

Hi,

Thanks for that detailed explanation. I'll try to sum it up very quickly and hope that I understood you correctly.

Basically, you want to dynamically set a module variable via user code. In general, that's not possible, but I created a small sample which allows you to set the value of an existing module variable via user code. You'll simply need to pass the name (it's not possible to pass a reference as a parameter) of the variable and the new value to the method.

SetModuleVariable.png

Also, please find a small sample solution here:
ForumSetVariableTest.zip
Cheers,
Robin :mrgreen:
You do not have the required permissions to view the files attached to this post.

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Mon Aug 20, 2018 2:37 pm

Almost there but ... this sets a module variable not a repository variable.

Let me give a further example...
I have a repository item representing a list and I want to e able to select individual elements within this list from within one recording.

I can get a single element from the list using spy but then I want to change it to something like this ...
LIST1000 /list[@controlid='1000']
GenericListItem listitem[@text=$generallistvalue]

I then want to do something like this in the RECORDING

user code SetVariableTo $generallistvalue "itemX"
Mouse Click GenericListitem

/.... more steps .../

user code SetVariableto $generallistvalue "itemY"
Mouse Click GenericListitem
/.... more steps ..../

.....
So my usercode in psuedo-code would look like this ...
sub SetVariableTo (VariableNAME, NewValue)
Find the variable in the repository which has this name
Set the value of this variable to NewValue
end sub

(Please note that I have heard the phrase "reflection" thrown about but I don't know how to do this or if it will really help.)
Or perhaps, it could be something like
sub SetVariableTo (repositoryItemWhichHasTheVariable, theVariableName, NewValue)
using repositoryItemWhichHasTheVariable
set the value of the variable called theVariableName in this item to NewValue
end sub

Then I would be able to pass in the GenericListItem as either a repoinfo or adapter (whichever is required) and the variable name and new value.
I can't find a way to get a variable from it's name

Finally, I could use a simplified version of this ...
sub SetVariableTo (repositoryItemWhichHasTheVariable, NewValue)
using repositoryItemWhichHasTheVariable
set the value of the variable WHOSE NAME I HAVE FIXED in this item to NewValue
end sub

This is less generic but would solve the majority of my problems.
To be honest, with all the problems I am having doing this, I probably could have re-written a lot of my tests, but I am still intrigued if this can be done.

Also, can you write in VB perhaps as I am not so familiar with cs.

Many thanks for your help.

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Wed Aug 22, 2018 12:29 pm

Hi,
"Almost there but ... this sets a module variable not a repository variable."
This variable can be used within your RanoreXPath. So, i guess that's exactly what you need.

ForumSetVariableTest - Ranorex Studio.png
Cheers,
Robin :mrgreen:
You do not have the required permissions to view the files attached to this post.

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Aug 28, 2018 12:41 pm

Oh - so I was missing something pretty obvious.
However, I still have one problem ...
I really want the SetVariableTo function / Sub to be in a separate UserCodeCollection. I have put the code in there ...
[UserCodeCollection]
public class UserCodeCollection1
{
// You can use the "Insert New User Code Method" functionality from the context menu,
// to add a new method with the attribute [UserCodeMethod].

/// <summary>
/// This is a placeholder text. Please describe the purpose of the
/// user code method here. The method is published to the user code library
/// within a user code collection.
/// </summary>
[UserCodeMethod]
public static void SetVariableTo(string variableName, string value)
{
var moduleVariable = this.GetType().GetProperty(variableName);
moduleVariable.SetValue(this, value);
}

}

HOWEVER ... this does not compile now because "this." refers to the recording/module class which is not known in this context.
Can I get "this." to know which class is referred to?

I am not very familiar with C# so, again, I may be missing the obvious. And I have not done anything like this in VB.NET.

Sorry.
Kevin

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Aug 28, 2018 5:15 pm

it used to be so easy with a separate generic code module usable by all my recordings which contained
Sub SetVariableTo(Byref Variable as String, NewValue as String)

Now I cannot use this in a separate code module as I get the ByRef removed. I wish I had not upgraded at the moment.
I do hope we can find a (simple?) solution.
I will need it in VB.NET since that is what my original Recording Modules are in.

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Wed Aug 29, 2018 1:38 pm

Hi,
In each recording where I wish to use my SetVariableTo sub, in the usercode.vb I would include the line
inherits genericusercode
Why would you need to set the variable in a different module?

Cheers,
Robin :mrgreen:

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Wed Aug 29, 2018 3:19 pm

yes. That is what I used to be able to do...
GenericuserCode.vb
contained SetVariableTo(ByRef Variable as String, NewValue as String)

In each recording where I want to use SetVariableTo, I would add "inherits GenericUserCode" e.g.
Public Partial Class TCMSDynamicsGlobalConfigAdd
inherits GenericUserCode

Private Sub Init()
' Your recording specific initialization code goes here.
End Sub
End Class

This meant I could use SetVariableTo and several other subs which I had written from anywhere in the recordings.
After upgrade to the latest version the byref has been removed, the sub has been changed to a function. Thus ...
FROM ...
SetVariableTo(itemindex, "1")
TO ...
itemindex = SetVariableTo("1")

Since this change has been made in the Ranorex generated code I am not able to edit it.

Note that I am not always setting the value of itemindex. It could be any variable in the repository. VB.NET with byRef worked - Now it has stopped.

Hope that clarifies things. Also, I am still not familiar with c# :D , sorry.

User avatar
RobinHood42
Posts: 324
Joined: Fri Jan 09, 2015 3:24 pm

Re: Removal of ByRef when creating using code causes a problem

Post by RobinHood42 » Thu Aug 30, 2018 8:02 am

Hi,

You could create a user code collection with the following method:

<UserCodeCollection> _
	Public Class MyCodeCollection
		' You can use the "Insert New User Code Method" functionality from the context menu,
		' to add a new method with the attribute [UserCodeMethod].

		''' <summary>
		''' This is a placeholder text. Please describe the purpose of the
		''' user code method here. The method is published to the user code library
		''' within a user code collection.
		''' </summary>
		<UserCodeMethod> _
		Public Shared Sub SetVariableTo(variableName As String, value As String)
			Dim moduleVariable = NameOfYourRepository.Instance.[GetType]().GetProperty(variableName) //Change NameOfYourRepository
			moduleVariable.SetValue(NameOfYourRepository.Instance, value) //Change NameOfYourRepository
		End Sub
	End Class

This method can then be called within every recording module:
UserCodeAction.png
The method directly changes the repository variable value.

Cheers,
Robin
You do not have the required permissions to view the files attached to this post.

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Sep 04, 2018 12:21 pm

OK, I think this maybe closer but ...
I defined the user code collection and the sub as
<UserCodeCollection()> _
Public Class GenericUserCodeCollection
' You can use the "Insert New User Code Method" functionality from the context menu,
' to add a new method with the attribute [UserCodeMethod].

''' <summary>
''' This is a placeholder text. Please describe the purpose of the
''' user code method here. The method is published to the user code library
''' within a user code collection.
''' </summary>
<UserCodeMethod> _
Public Shared Sub SetVarTo(variableName As String, newValue As String)
Dim moduleVariable = MyRepository.Instance.GetType().GetProperty(variableName)
moduleVariable.SetValue(MyRepository.Instance, newValue)
End Sub
End Class

And in my recording I have,
UserCode SetVarTo(String variableName, String newValue) $TaskToRun CheckagainstBenchmark

But when I run this line I get an error on the sub line "moduleVariable.SetValue" ...
Object Variable or With block variable not set

Sorry to be a pain. I really want to understand this and make it work. :oops:

Kevin

KJG
Posts: 18
Joined: Wed Jul 18, 2018 9:08 am

Re: Removal of ByRef when creating using code causes a problem

Post by KJG » Tue Sep 04, 2018 3:05 pm

I tried with this code where gettype is not in [] and with it in [].