COM objects for Cheepskates
So you want to make com objects, but don't want to fork out cash for visual basic/other ide's?
Here's the simple, free and _EASY_ way to do it.
Requirements:
Javascript, Jscript, VBscript, Perlscript, REXXscript or any other script supported by windows scripting host.
Introduction
(previois posts)
That covers the background of this whole thing fairly well. So, here we are.
Part One: Working With My First Com Object
I read the help file entry and sat confused. I looked at the example and didn't get far either.
Here's my better commented version.
excel {
;Excel.Application is what the Excel com object is filed under the the WINDOWS REGISTRY. It has a clsid, which is a bunch of numbers in brackets, like:
;{00000-00000-00000-0000}
;That doesn't concern us yet.
;Action:
;Opens a new com object, and label it "excel" of type Excel.Application.
comopen excel Excel.Application
if ($comerr) {
;if it doesn't open, give up and yell at the user
echo comopen failed
halt
}
;Original: check if excel window is visible
;Extended: check if excel window is visible. Do this by
;accessing the public method VISIBLE in object EXCEL (opened earlier) with
;1 = DISPATCH_METHOD
;2 = DISPATCH_PROPERTYGET
;1 + 2 = 3, which explains that bit.
;That tells it to GET a return value from a METHOD
;Think of it like a custom $identifier - alias monkey { return fleas }
;$monkey returns the word "fleas", BUT its an alias rather than a varible.
;mIRC doesn't have return types, but other langauges do. More on that later.
if ($com(excel,Visible,3) == 0) {
echo $com failed
goto finish
}
echo Visible: $com(excel).result
;Original: make excel window visible
;Extended: make excel window visible. Do this by
;accessing the public method VISIBLE in object EXCEL (opened earlier) with
;1 = DISPATCH_METHOD
;4 = DISPATCH_PROPERTYPUT
;That tells it to PUT(pass) a value to a METHOD
;Again a custom $identifier - alias monkey { set %secret_var $1- }
;$monkey(fleas) sets a varible which the user can't see (PRIVATE some might say)
;this returns 0 for "we screwed up", or something else for "its all good"
if ($com(excel,Visible,5,i4,1) == 0) {
echo $com failed
goto finish
}
; check visibility again
;look above
if ($com(excel,Visible,3) == 0) {
echo $com failed
goto finish
}
echo Visible: $com(excel).result
:finish
;get rid of the stupid thing, we are sick of it.
comclose excel
}
mIRC isn't a real programming language. Its a scripting language. Its had bits cut out of it left right and center, for ease of use.
The differences between mIRC and a real programming language:
mIRC:
mIRC uses "aliases", which are "simulated functions".
mIRC uses varibles which automatically convert data.
mIRC isn't object oriented.
+more
Java:
Java uses real functions
Java uses primitive types for its varibles. For instance, if you have a varible named "x" of the type "int" (Integer), you can't put the String "Bob" into it and expect it to work. The reason for this is it is trying to use the least amount of memory possible - an Int takes up less memory than a string (how long is a piece of string, we don't know so we just take up a lot of space to start off with and hope!)
Java is Object Oriented.
What is the Object Orientated nonsense?
Well, think back to making a dialog.
What mIRC script does is create a basic dialog object and that in turn adds other objects (buttons, text boxes, etc). You can create your dialog by /dialog -m <table> <name>
What does that mean?
You can create 2 copies of one dialog table with different names
They are the same beast, just different INSTANCES of them. Sadly mIRC doesn't do this often with aliases and other language features, but in most cases it doesn't need to.
Whats the use of it all?
Lets look at this:
$com(excel,Visible,3)
Somewhere in Excel.Application's code is soemthing like this
private int Visible;
public int get_Visible() {
return Visible;
}
public int set_Visible(int Value) {
Visible = Value;
makeAppVisible;
return 1;
}
What that all is is as follows:
Line 1: a Varible named "Visible". It stores an int or Integer (whole number). It is PRIVATE, so only functions in the same program can "see" it. mIRC can't meddle with it, as that would be dangerous.
Line 2: a Method named get_Visible. It returns the value of Visible, which can't been seen by anything else externally. It is PUBLIC which means that everyone can see & use it. It takes no arguments (parameters, $1- etc).
Line 5: A method name set_Visible. It sets the value of Visible to Value (they are both integers so there is no need to convert from one type to another). It returns 1 if its successful. If its not successful, it won't return anything (NULL). It also does all of the code to show the app
This whole process is known as "Encapsulation", and is a key programming technique in many successful languages today.
So, here we are.
Reality:
Excel object
-Property Visible
-Method get_Visible
-Method set_Visible
What mIRC see's:
Excel
-Method Visible
get_ & set_Visible are combined into a "Visible" method for teh ease of use mIRCers. DISPATCH_METHOD + DISPATCH_PROPERTYGET simply calls the get_Visible method, DISPATCH_METHOD + DISPATCH_PROPERTYPUT does the same with set_Visible
I think we have covered enough theory about implementing for you to get a rough grasp of things to come.
Part 2: Creating my first COM object.
Run off to msdn.microsoft.com, downloads, windows script, and get Script Component Wizard.
It will make things easier, like assiging a CLSID.
Run it.
Follow the prompts and make a new com object, called "Monkey"
Scripting Langauge of your choice...
Scriptlet, not DHTML
Add property "Version", value "1.0.0", get only
Add property "Temp", value "Bob string!",put, get
Add method inputPrompt, arguments text
"Finish"
You should end up with something like this:
<scriptlet>
<Registration
Description="monkey"
ProgID="monkey.Scriptlet"
Version="1.00"
ClassID="{65378720-7da6-11d7-ab3c-525400edd75c}"
>
</Registration>
<implements id=Automation type=Automation>
<property name=version>
<get/>
</property>
<property name=temp>
<get/>
<put/>
</property>
</implements>
<script language=JScript>
var version = "1.0.0";
var temp = "Bob String";
function get_version()
{
return version;
}
function get_temp()
{
return temp;
}
function put_temp(newValue)
{
temp = newValue;
}
</script>
</scriptlet>
PHWOAR! Find whewre its been generated to (path\monkey.sct). right click and "register" it with windows, if it has problems it will tell you.
Problems appear in the form of "[line,col] Problem text". I'll let you debug it.
Once its registered, the rest is easy.
Go into mIRC and use the excel example alias as a guide.
;monkey.Scriptlet
alias monkey {
;open a new monkey.Scriptlet
comopen monkey monkey.Scriptlet
;if it won't open, yell out and stop doign stuff
if ($comerr) { echo comopen failed | halt }
;annoy it for stuff
var %test = $com(monkey,version,3)
echo -a version: $com(monkey).result
var %test = $com(monkey,temp,3)
echo -a temp1: $com(monkey).result
;change the value of temp to fish
if ($com(monkey,temp,4,string,fish) == 0) {
echo -a Didn't work
halt
}
var %test = $com(monkey,temp,3)
echo -a temp2: $com(monkey).result
comclose monkey
}
As you can see, $com.result holds the returned data.
Muddle through that, my fingers are tired and I want pie.
Part 4: Where's my part 3?
Well if your sharp enough you'll have noticed that its missing someting, not just a part 3. All I've shown you is how to get and set properties in your COM object, not how to call methods. Or have I? I've shown you how to get/set properties through their METHODS, so you can make your own method calls to custom methods (functions). Here's a tip, tho, don't try to return anything funky! Stick to your basic types, and you'll be fine.
Part 5:Real world applications
What can you do in Jscript you can't do in mIRC:
Better maths object (ie proper Psuedorandom numbers!)
An arguments object - better than using $1- for stuff that needs switches
Better Boolean object (for when $iif just doesn't cut it)
Enumerator - enables you to use a collection with an index (array styles)
Arrays! (not 2d tho, sigh)
Easier activeX com object implementation (well, maybe...)
Better error handling
Functions as objects! This is good enough to include an example methinks:
Example 1
function add(x, y)
{
return(x + y); //Perform addition and return results.
}
Example 2
var add = new Function("x", "y", "return(x+y)");
In either case, you call the function with a line of code similar to the following:
add(2, 3);
A Global object
A slightly better regexp object (yes, OBJECT is better in this case sometimes)
More organised string handling (its an OBJECT! gasp!)
VBarrays even
Of course its up to you to decide whats the _best_ option for the task, the script, and your ability. You should script for the end user rather than for what looks good for you.
If this is confusing, yes, look for a second edition (much cleaner, and neater. I'll probably even post it on my website.) Email me @
gekko_dev@hotmail.com if you have questions or queries.