loading an assembly into a .net System.Windows.Forms.Form

Technology specific object identification, supported applications, web technologies, and 3rd party controls.
michael.gorman
Posts: 3
Joined: Mon Jun 18, 2018 8:42 pm

loading an assembly into a .net System.Windows.Forms.Form

Post by michael.gorman » Mon Jun 18, 2018 9:03 pm

We are currently evaluating replacing SilkTest with ranorex. SilkTest has a feature that allows the user to "inject" a dll into the AUT and invoke the members of that dll. So instead of constantly calling "Invoke" in the testing app we have an external dll that gets loaded into the same domain of the AUT and then we invoke a single call from the testing app to the AUT and the code actually runs within the AUT process. I should also note that we are not using ranorex studio or even a repository but just utilizing the APIs from a C# project. Is there a way to do this in Ranorex, I've searched the help files and dlls but could find anything, I would imagine there ranorex has this capability because it injects itself into the AUT process but maybe it a hidden feature?

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: loading an assembly into a .net System.Windows.Forms.Form

Post by ahoisl » Tue Jun 19, 2018 2:09 pm

Ranorex provides the same functionality for Windows Forms controls (since 2007) by means of the Control adapter. The corresponding method is called InvokeRemotely and allows to pass in a delegate that is invoked in the other application, passing in the WinForms control InvokeRemotely was called for.

The only thing you need to make sure is that all input parameter and return values are serializable (if you need any), e.g. simple types like int, string, or lists of such types.

The following (old, but still valid) blog provides some more info on that topic:
https://www.ranorex.com/blog/transferin ... t-control/

Regards,
Alex
Ranorex Team

michael.gorman
Posts: 3
Joined: Mon Jun 18, 2018 8:42 pm

Re: loading an assembly into a .net System.Windows.Forms.Form

Post by michael.gorman » Tue Jun 19, 2018 3:28 pm

Intersting, so would I be correct in saying that I could call invokeremotely twice, one delegate to load the assembly into the AUT then another delegate to invoke any method in that now loaded assembly?

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: loading an assembly into a .net System.Windows.Forms.Form

Post by ahoisl » Tue Jun 19, 2018 3:30 pm

michael.gorman wrote:Intersting, so would I be correct in saying that I could call invokeremotely twice, one delegate to load the assembly into the AUT then another delegate to invoke any method in that now loaded assembly?
You should be able to call methods in that assembly from the first call already...

Regards,
Alex
Ranorex Team

michael.gorman
Posts: 3
Joined: Mon Jun 18, 2018 8:42 pm

Re: loading an assembly into a .net System.Windows.Forms.Form

Post by michael.gorman » Tue Jun 19, 2018 6:06 pm

Additional information: Action 'invokeremotely' failed on element '{Form:DesktopFormStandalone}'
Looking at the inner exception it appears to be attempting to load the assembly that I am already running from into the AUT app domain just to execute the custom code, I don't want that at all. Is there another way to crack this egg cause I can't have my monster of a testing app actually loaded into the AUT?
Ranorex.Control win1 = Host.Local.FindSingle<Ranorex.Control>("/*[@handle='462902']");
win1.InvokeRemotely(LoadAssembly);

public static Object LoadAssembly(System.Windows.Forms.Control ctrl, Object input)
{ 
  return null;
}
Ranorex.ActionFailedException occurred
HResult=-2146233088
Message=Action 'invokeremotely' failed on element '{Form:DesktopFormStandalone}'.
Name=invokeremotely
Source=Ranorex.Core
StackTrace:
at Ranorex.Core.Element.InvokeAction(String name, Object[] args)
at Ranorex.Control.InvokeRemotely(RemotelyInvokedDelegate deleg)
at R3.Class1.foo() in D:\builds\blast\prototypes\Ranorex\R3\R3\Class1.cs:line 38
InnerException:
HResult=-2146233076
Message=Unable to find assembly 'R3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Source=mscorlib
StackTrace:
Server stack trace:
at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at Ranorex.Libs.WinForms.IControlProxy.InvokeRemotely(Delegate deleg, Object inputData, Int32 timeout)
at Ranorex.Libs.RemotingBreaker`1.Invoke[TRes](Func`2 call)
at Ranorex.Plugin.WinFormsFlavorElement.InvokeRemotely(RemotelyInvokedDelegate deleg, Object inputData, Duration timeout)
at Ranorex.Plugin.WinFormsFlavorElement.InvokeAction(Element element, String name, Object[] args)
at Ranorex.Core.Element.InvokeAction(String name, Object[] args)
InnerException:

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: loading an assembly into a .net System.Windows.Forms.Form

Post by ahoisl » Tue Jun 19, 2018 10:29 pm

michael.gorman wrote:Is there another way to crack this egg cause I can't have my monster of a testing app actually loaded into the AUT?
Put the "LoadAssembly" method in a separate DLL (=library project) and make sure that the DLL is compiled to target "Any CPU". Then only that DLL should be loaded.

Regards,
Alex
Ranorex Team