Accessing Other Programs - Revisited...

Posted by Shadowfyr on Sat 10 Jan 2004 10:35 PM — 3 posts, 9,648 views.

USA #0
Ok. I am still waiting for replies from a few people for suggestions how to get around the Event handling issue. However... Here is the problem:

1) Script compatible objects/programs use a different Dispatch handler than the IUnknown or IDispatch that normal COM does. This special handler somehow give the engine extra data on the properties, callbacks and events of the object, so that it can use them.

2) Only objects that the scripts client specifically adds to the list of available objects are bindable in the script engine.

3) Dynamically created objects, using CreateObject, cannot be bound to the scripts even handler, even if they provide this special interface.

4) If an object is not designed to work with scripting, you are screwed anyway, since you can never bind it to the script engines event handler.

Thanks Microsoft!!! This is really %#$^ convenient. lol

What this means is that for Mushclient to allow external objects to generate events, Mushclient will need some sort of internal object collection, it will have to create the objects and it will need to recieve the events and call the appropriate script routines. This isn't impossible, a single class could probably handle all of it, since in C++ you can intercept and handle events, even if you have no real idea what they where before hand. It is just a tad more complicated than I know how to manage myself, if I was coding it. ;)

But seriously, the only real solution I can see is something like adding a new feature to the plugins XML spec:

<object
name="WinAmp"
Init="winampCOM.application"
CLSID="..." <!-- Optional -->>
<Event
name="SongChange"
Params=1>
</Event>
</object>

Or something like that. In the above case, the sub would need to then be named "WinAmp_SongChange". It might need some tweaking, but the idea is to provide a collection of objects, tied to the plugin, that Mushclient can handle events from.

The only current alternative is to waste time coding a DLL or EXE that used CallPlugin and have it sit in between the client and the script. I am only guessing, but I a pretty sure that would mean also coding stuff to pass on every callback and property for the object. For something like the one above, this goes beyond silly and right into the realm of flat out stupid, since there is only the one event that needs to be captured, but about 50 commands and properties you would have to have the DLL or EXE pass on as well.

Most programs are probably like this, dozens, or even hundreds of commands, but only a handful of events that Mushclient and the scripts it runs can't respond to. Just because you 'can' use CallPlugin doesn't mean it is efficient or a completely dumb solution. :(

Anyway. It is something to consider. I still hope to find some solution, even if only an example of how to simply manage such a collection of previously unknown objects types.
Australia Forum Administrator #1
What I *think* you are asking for here is a custom way of calling a script. At present the scripts do their stuff and then the script exits. They do their stuff at well-defined points, eg. a trigger or alias fires, the world connects, an MXP tag arrives etc.

You want to add an invocation point, eg. when a song finishes playing, am I right?

If this is the case, then it might be possible to define custom script entry points, if I could know what the external event is, that should trigger such an event.
USA #2
Yeah. Basically.

The only issue I see is how the object is created. Can you handle events from something created in the script:

set ab = createobject("blah.blah")
LinkEvents "MyObject", ab

or if Mushclient needs to handle it all, by defining the object in XML, along with its events, then passing a reference to the script so that:

<OBJECT ID="MyObject"...

automatically becomes the variable 'MyObject' in the script, which appears to be what IE does, but even you assumed that something like this had to be possible, until I pointed out that just placing a sub in the script called 'SongChange' didn't work, because vbscript didn't automatically add the winamp object to its event list. It should, but when MS designed ActiveScript they didn't even have the GetRef command, it only appears starting in 5.0. The only way to declare and use event driven subs prior to 5.0 was using IE and the OBJECT keyword.

GetRef itself appears to be intentionally deficient because IE's method made it possible to link malicious objects into web pages, while GetRef can only link objects built directly into the DHTML spec for the browser. In the case of Mushclient, this pretty much makes using existing event driven COM intefaces impossible and is not really as big a concern. Its not like we need to worry about malicious objects sending other people our passwords from inside a plugin or logging stuff as we play...

I think some sort of custom method of linking or declaring objects of this type would definitely be useful. But to better understand my reasoning, consider an example of an external database window. Which is better?

1.Making a window that has all the fields shown and fires events:

' Obviously this could be done another way, but not if this event was 'built' into an
' existing program, instead of one you write yourself.
sub DBWindow1_Found (Name, Size, Notes)
  note "Name: " & Name
  note "Size: " & Size
  note " "
  note "Notes: " & Notes
end sub

sub DBWindow1_Deleted
  colournote "red", "black", "Record Deleted!"
end sub

... 'More events.


2. One that forces you to use CallPlugin:

sub DB_Found (Big_string)
  temp = split(Big_string, ";") 'Gee hope no one used ; in the notes..
  Name = temp(0)
  ...
end sub

The problem with method 2 is not only needing to split the parameter to get them back. You also can't use this method with existing ActiveX programs (at least not without adding another object in between that does support this method and crams all the stuff together). The maximum string length can be exceeded fairly simply. And you can never use it with anything other than Mushclient (again, unless you design the main object to run without it, then shoehorn another dll or program in between that repackages the data).

I suspect most people would prefer the first option over the major complications and limitations created by the second method.