views:

750

answers:

2

Hi,

I'd liked to know whether it is possible to call a function in VBScript from C#. Let me try to clarify. I'm using an application (Quick Test Professional or "QTP") that automates another application, mostly using VBScript. There is the ability, via an add in model, to extend the test functionality by writing add-ins to the testing application (QTP) that are .NET assemblies. The basic workflow is that the VBScript tests automate the test application, and can call methods on a class in the extensibility add in assembly to do more complicated things. This part works fine.

What I'd like to know is whether it is possible for my C# code (in the extensibility add in assembly) to call back to a function in the VBScript. I don't think the test application framework (QTP) explicitly supports this, so I'm wondering if there is any way to do this using standard interop techniques. I was half way thinking of using GetRef() to get a reference to the VBScript function of interest, passing this as a parameter to a method I call in the extensibility addin (I suspect I would run into marshaling issues even at this point?) and then within the C# code of my extensibility add in, somehow call a method on this object; this is where I'm completely lost (since I don't know how to do this without the necessary type information normally used in reflection).

I'm thinking this may not be possible, but would like confirmation if that's the case.

Thank you!

A: 

How does the VBScript call the C# code? I suspect that it is really calling on QTP, and QTP is calling the C# code. In that case, only QTP could possibly call the VBScript back.

Under what circumstances would your C# code call back? I doubt that VBScript can be called back asynchronously.

John Saunders
I don't know how the VBScript calls the C# code. If I had to guess, think you're right; it's likely relying on QTP and QTP is calling the C# code.Ideally, my C# code would callback the VBScript method in response to an event raised in the control, which the C# code subscribed to.
Yeah, that's really not going to work, as far as I can see. VBScript is a scripting language. It does not understand events, or multi-threading, and I'm sure it has no idea it might be called asynchronously. Consider: could you do this with just pure VBScript? Have a VBSCript script call a VBScript function that later "calls back" the original? I see no way to do that.
John Saunders
Yes, VBScript does understand events in different ways, depending on the hosting application hythlodayr references a couple of web pages below. (The first reference is most appropriate).
A: 

That's a toughie.

You MAY want to try writing an event handler in the VBScript side for the .NET component and raising an event on the .NET side when you want the function to be called.

Just be warned it may not even work, as it really depends on QTP's scripting engine. And even if it should, don't be surprised if it becomes an exercise in frustration.

See examples on WSH and event handling http://msdn.microsoft.com/en-us/library/ms974564.aspx Again, this probably won't apply to QTP, but it's to give you an idea of potential approach to the problem.

Edit: Additional link which may or may not help!

http://www.west-wind.com/presentations/dotnetfromVfp/DotNetFromVfp_EventHandling.asp

hythlodayr
It's VBScript. Does it have events?
John Saunders
I had previously had the same thought, and found the same (first) page you referenced. However, I don't think QTP is using WSH and none of the other approaches (in the MSDN reference) to subscribe to events in VBScript seemed to work in my scenario. I think this is because I can't influence what is passed into the scripting engine (as I'm not QTP), and thus use the 'automagic' and calling functions approach can't be used.
@ John: Event *handling* has been around for quite some time now (think Internet Explorer). But its support is inconsistent and largely dependant on the implementation of the scripting engine.@ Notre: Sorry, then. The vendor may be better equipped to give you an answer.
hythlodayr
The vendor hasn't been too helpful (in a related question I posed to them) and I find nothing in their documentation that suggests it is supported. That's why I thought I'd post here to see if there was any thing I might have been missing, from a more general interop perspective.
I had totally forgotten Object_EventName. Even so, that would apply to COM events. That would be a bit of a mess to call from C#, and a maintenance problem, considering how few people remember COM eventing.
John Saunders
I would be okay with the Object_EventName 'automagic' approach, but even that relies on the application (QTP, in this case) passing an object into the scripting engine and putting the scripting engine into 'connected' mode, so it won't work for a 'lowly' add in :(
Back to your original thought: GetRef.Marshal.GetDelegateForFunctionPointer could be the answer, but I have no idea whether this would work or not (which was your original question).
hythlodayr
Hmm! Marshal.GetDelegateForFunctionPointer. I didn't know about this method. This might just work. I'll have to give this a try.
I tried this. Unfortunately, I couldn't even call into my C# code. Once I tried to pass in GetRef("funcionName") as a parameter, things failed before even getting into my C# code :(
I doubt you're still reading this, but GetRef is a funny beast. Since you have to use SET with GetRef, it means GetRef is returning some sort of COM object. Make sure you're using the correct parameter type for your .NET code. Maybe just start with the IUnknown interface as the parameter to see if you even get into your C# code.
hythlodayr