Welcome
Contents |
What Is COM?
COM stands for Component Object Model. It is a Microsoft Windows technology and is usually used to provide access to functionality found in a certain application.
Here is Microsoft's definition of COM (in bold):
Microsoft COM (Component Object Model) technology in the Microsoft Windows-family of Operating Systems enables software components to communicate. COM is used by developers to create re-usable software components, link components together to build applications, and take advantage of Windows services. The family of COM technologies includes COM+, Distributed COM (DCOM) and ActiveX® Controls.
mIRC cannot create COM objects, but it can use them (with the exception of DCOM and ActiveX controls.)
Terminology Used In This Article
- Connection A connection to a COM object.
- Member The name of a method, property, etc inside of an object.
- Method A function inside of a COM object that you can call. Some of these return a value, but not all.
- Object A COM object (a class inside a dll that you can use.)
- Property A property inside of an object that you can get/set. Used to turn settings on/off.
Is COM support in mIRC just as powerful as it is in a language like say, VBScript?
No. Here's why:
- mIRC cannot catch events from objects. This feature has been suggested multiple times so hopefully we'll see it in a future version.
- mIRC cannot call methods in an enumeration ($comval limitation.)
- mIRC doesn't let you retrieve long results from objects (no &binvar support.)
- Various bugs (some are unconfirmed or only happen occasionally); [1] [2] [3] [4] [5] [6]
Objects You Might Find Useful
Note: you'll rarely find any documentation/references on objects that use mIRC scripting syntax. Documentation is usually written for JScript or VBScript users, so basic knowledge of those languages is a plus, but not a must.
- Scripting.FileSystemObject
- Description: This object lets you do lots of filesystem related tasks, such as move/copy/delete/create files.
- Reference: [7]
- WbemScripting.SWbemLocator
- Description: This is what is known as WMI, or the Windows Management Instrumentation. It can be used for a whole lot of computer related activities and contains a wealth of system information.
- Reference: [8]
- WMPlayer.OCX
- Description: This is the windows media player object, so you can expect to find lots of audio/media playing functionality in this.
- Reference: [9]
- WScript.Shell
- Description: Read system information and environment variables, work with the registry or manage shortcuts, amongst other things.
- Reference: [10]
How can I use COM objects in mIRC?
You can use COM objects through the use of the /comopen command, $com, $comcall and $comval identifiers. You can check for errors using $comerr. Objects can be cleared up after use by the /comclose command. /comreg can be used to register/unregister an unregistered/registered COM OCX or DLL file.
Do not expect an instant understanding of these as this is a complex topic. If you came to mIRC scripting from a language with great COM support like VB or JScript, you might find the concept a little easier to grasp.
/comclose
Description
This is used to close an open COM connection.
Format
/comclose <name>
Switches
None.
Parameters
- <name> The object you want to close. This is the name you specified in /comopen.
Points To Note
None.
Examples
comopen a Scripting.FileSystemObject if ($com(a)) comclose a
This will open and close the 'a' object.
var %obj = obj $+ $ticks .comopen %obj WbemScripting.SWbemLocator if ($com(%obj)) .comclose %obj
This will open and close the 'obj<ticks>' object.
Hacks
None.
/comopen
Description
The /comopen command is used to open a COM connection to a certain object.
Format
/comopen <name> <progid>
Switches
None.
Parameters
- <name> The name parameter is a name you give to the COM connection which you will later use to access the object's properties and methods.
- <progid> The progid parameter is the name of the object you want to connect to. Examples include; WScript.Shell, Scripting.FileSystemObject, Excel.Application, etc.
Points To Note
- You can find a list of all registered progids on your system under the HKEY_CLASSES_ROOT registry key. Usually every progid will be accompanied by a key of the same name with a version number at the end, for example; WMPlayer.OCX and WMPlayer.OCX.7 or WScript.Shell and WScript.Shell.1
- It's a good idea to give COM connections a unique name, such as <name> $+ $ticks (the number of milliseconds since you turned on your computer.)
- You should always cleanup objects when you've finished with them by using /comclose.
Examples
/comopen a WScript.Shell
This will open the object 'a' to WScript.Shell.
var %obj = obj $+ $ticks .comopen %obj WMPlayer.OCX
This will open the object obj<ticks> to WMPlayer.OCX, store the name in a variable for later use (because $ticks changes) and silence the output of /comopen.
Hacks
None.
/comreg
Note: Throughout this section you can assume the word 'register' means 'unregister' if you use the -u switch in /comreg.
Description
/comreg can be used to register an unregistered COM dll file.
Format
/comreg [-u] <file>
Switches
- -u This switch is used to unregister a COM dll.
Parameters
- <file> This is the file you want to register.
Points To Note
None.
Examples
/comreg c:\test.dll
This will register c:\test.dll.
/comreg -u test.dll
This will unregister test.dll from the mIRC directory.
Hacks
None.
$com
Description
This can be used to check if a connection is open and to call a method or set/get a property inside of an object.
Format
- $com(name/n)
- $com(name,member,action,type1,value1,...,typeN,valueN).[argerr/dispatch/error/errortext/progid/result/unknown]
Parameters
- name/n The name of the connection you want to check is open, or a number to return the Nth object.
- name The name you gave to the connection in /comopen.
- member The name of the function you want to call, or the property you want to get/set.
- action A sum of the following:
- 1 This means you want to call a method.
- 2 This means you want to return a value.
- 4 This means you want to set a property.
- 8 This means you want to set a property by reference.
If you want to call a method that returns a value, for example, you should use 3.
- type This is the type of parameter you're passing to the member. This can be one of the following (descriptions taken from ShredPlayer's tutorial ([11])):
| Type | Description |
|---|---|
| bool | True or false |
| bstr | Basic string |
| cy | Currency. -922337203685477.5625 to 922337203685477.5625 |
| date | Date or time. |
| decimal | A decimal number. +/-79,228,162,514,264,337,593,543,950,335 with no decimal point. +/-7.9228162514264337593543950335 with 28 places to the right of the point. |
| dispatch | A pointer to an IDispatch interface. |
| error | A 32-bit error code. |
| int | Integer. -2147483648 to 2147483647 |
| i1 | 1-byte signed integer. Should be -128 to 127 but is actually 0 to 255. |
| i2 | 2-byte signed integer. -32768 to 32767 |
| i4 | 4-byte signed integer. -2147483648 to 2147483647 |
| r4 | Real, 4-byte floating number. 1.17549435E-38 to 3.40282347E+38 |
| r8 | Real, 8-byte floating number. 2.2250738585072014E-308 - 1.7976931348623157E+308 |
| uint | Unsigned integer. 0 to 4294967295 |
| ui1 | 1-byte signed integer. 0 to 255 |
| ui2 | 2-byte signed integer. 0 to 65535 |
| ui4 | 4-byte signed integer. 0 to 4294967295 |
| unknown | A pointer to an IUnknown interface. |
| variant | Can include string, date, time, boolean or numerical values. |
- value The value you want to pass as a parameter to the object.
Properties
- .argerr Nth argument that caused the error.
- .dispatch Returns $true if a dispatch pointer is available for the connection.
- .error Error code.
- .errortext Error text. One of the following (taken from ShredPlayer's tutorial ([12])):
| Errortext | Meaning |
|---|---|
| DISP_E_BADPARAMCOUNT | The number of elements provided is different from the number of parameters accepted by the method or property. |
| DISP_E_BADVARTYPE | One of the parameters is not a valid variant type. |
| DISP_E_EXCEPTION | The application needs to raise an exception. |
| DISP_E_MEMBERNOTFOUND | The requested member does not exist, or the call to invoke tried to set the value of a read-only property. |
| DISP_E_NONAMEDARGS | Does not support named arguments. |
| DISP_E_NOTACOLLECTION | Does not support a collection. |
| DISP_E_OVERFLOW | One of the parameters could not be coerced to the specified type. |
| DISP_E_PARAMNOTFOUND | Correct number of parameters was passed but one or more parameters was incorrect. |
| DISP_E_PARAMNOTOPTIONAL | Parameter not optional. |
| DISP_E_UNKNOWNINTERFACE | The interface identifier passed in riid is not IID_NULL. |
| DISP_E_UNKNOWNLCID | The member being invoked interprets string parameters according to the LCID, and the LCID is not recognized. |
| DISP_E_UNKNOWNNAME | One or more of the given names were not known. |
- .progid Returns the progid of the object.
- .result The value returned by the member you called.
- .unknown Returns $true if an unknown pointer is available for the connection.
Points To Note
- Some methods will return an object. In these circumstances you can pass dispatch* <name> as a type and mIRC will create a new connection called <name>.
- Some methods will return an interface. In these circumstances you can pass unknown* <name> as a type and mIRC will create a new connection called <name>.
- You can pass an object as an argument to a method by specifying dispatch as the type.
- You can pass an interface as an argument to a method by specifying unknown as the type.
Examples
alias openremote {
.comopen a WScript.Shell
if ($com(a)) .comclose a $com(a,SendKeys,3,bstr,% $+ r)
}
This above will open Remotes.
alias noautostart {
var %obj = obj $+ $ticks
if ($com(%obj)) {
.echo -q $com(%obj,Settings,3,dispatch* %obj $+ settings)
if ($com(%obj $+ settings)) {
.echo -q $com(%obj $+ settings,autoStart,4,bool,false)
.comclose %obj $+ settings
}
.comclose %obj
}
}
The above will set the autoStart of WMPlayer.OCX's Settings object to false.
Hacks
You can use the $and, $or and $xor hacks to ignore the return value of the first $com call but gain access to $com().result, or a new object if the return value was an object/interface.
$comcall
Description
$comcall is exactly the same as $com except it's multi-threaded. $comcall will call an alias when a COM call returns instead of waiting for it.
Format
$comcall(name,alias,member,action,type1,param1,...,typeN,paramN)
Parameters
- alias The alias to call when a COM call returns.
Properties
None.
Everything else (parameters, etc) is the same as $com.
$comerr
Description
This is used after a COM related command to check if there were any errors.
Format
$comerr
Parameters
None.
Properties
None.
Examples
alias test {
.comopen a WScript.Shell
if ($com(a)) {
.echo -q $com(a,x,3,bstr,test)
if ($comerr) echo -a $com(a).error ~ $com(a).errortext
.comclose a
}
}
This will output an errornumber and text because 'x' is not a member of WScript.Shell.
Hacks
None.
$comval
Description
Returns member value for the Nth instantiation of the enumerated collection in name.
Format
$comval(name,N,member)
Parameters
- name The name of the COM connection.
- N The number of the instance in the collection.
- member The member name.
Properties
None.
Examples
alias processes {
var %a = a $+ $ticks, %b = b $+ $ticks, %c = 1, %d
.comopen %a WbemScripting.SWbemLocator
if ($com(%a)) {
.comclose %a $com(%a,ConnectServer,3,dispatch* %b)
if ($com(%b)) {
.comclose %b $com(%b,InstancesOf,3,bstr,Win32_Process,dispatch* %a)
if ($com(%a)) {
%d = $(,,$com(%a,Count,3)) $com(%a).result
while (%c <= %d) {
echo -a $comval(%a,%c,Name)
inc %c
}
.comclose %a
}
}
}
}
This will list all running processes.
Hacks
None.
Example Scripts
Here are a few of the COM scripts floating about on the net.
$memuse By FiberOPtics
Returns the amount of memory the given process is using.
;
; Usage: $memuse(process, N [, kmgt3])[.suf]
;
; Author: FiberOPtics
;
; Email: mIRC.FiberOPtics@gmail.com
;
;
; Description:
; ------------
; This snippet will return the memory usage of a running process.
; These values can be seen in the tab "Processes" from the "Windows Task Manager",
; under the column "Mem Usage". The output is by default in bytes, though can be
; formatted differently by specifying a third parameter. When specifying the .suf
; property, the result will have the formatting unit appended to the result.
;
;
; Parameters:
; -----------
; Required $1 = name of the process as seen in the Process list
; Required $2 = references Nth instance of the specified process
;
; --> N = 0 : returns total memory usage of all instances together
; --> N = 1 : returns memory usage of the first instance
; --> ...
;
; Optional $3 = parameters from the built-in $bytes identifier, to format
; the output: bkmgt3
;
;
; Examples:
; ---------
; //echo -a $memuse(mirc.exe ,0) -> returns total mem usage of all instances of mIRC in bytes
; //echo -a $memuse(winamp.exe, 1, m) -> returns mem usage of 1st instance of Winamp in megabytes
; //echo -a $memuse(notepad.exe, 2, k).suf -> returns mem usage of 2nd instance of Notepad in kilobytes
;
;
; Requirements
; -------------------
; mIRC 6.16 because of $comval
;
; Works by default on Windows versions: Vista, XP, 2000 Professional, or NT Workstation 4.0 SP4
;
; Windows 95 and 98 users can't use WMI, unless if they download the WMI
; core from http://www.microsoft.com/downloads
;
; For more info about WMI and its requirements check the url:
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp
;
;
; Updates:
; --------
; * Recoded alias completely
; * Added property .suf to show formatting when specified
; * Added :error label for cleanup in case of error
; * Added version check to see if mIRC is atleast version 6.16
;
alias memuse {
if (!$isid) {
echo -ac info * $!memuse: this alias can only be called as an identifier.
return
}
var %e = return $+($chr(3),$color(info),*) $!memuse:
if ($version < 6.16) %e this alias can only be used on mIRC versions 6.16 or higher.
if ($0 < 2) %e insufficient parameters.
if ($2 !isnum 0-) %e The N property can only be a positive integer.
if ($0 > 2) && ($3 !isin bkmgt3) %e unexisting parameter $3 for $!bytes.
if ($prop != $null) && ($prop != suf) %e property can only be .suf
var %loc = loc $+ $ticks, %wmi = wmi $+ $ticks, %col = col $+ $ticks
.comopen %loc WbemScripting.SWbemLocator
if ($comerr) %e Error opening locator object.
.comclose %loc $com(%loc,ConnectServer,1,dispatch* %wmi)
if (!$com(%wmi)) %e Error connecting to wmi.
.comclose %wmi $com(%wmi,ExecQuery,1,bstr*,SELECT WorkingSetSize $&
FROM Win32_Process WHERE Name = $+(",$1,"),dispatch* %col)
if (!$com(%col)) %e Error retrieving collection.
if ($comval(%col,0) == 0) { .comclose %col | %e no such process $1 }
var %i = 1, %result
while ($comval(%col,%i,WorkingSetSize) != $null) {
%result = %result + $v1
inc %i
}
.comclose %col
return $bytes($calc($gettok(%result,$iif(!$2,1-,$2),43)),$iif($3,$3,b)). [ $+ [ $prop ] ]
:error
tokenize 32 %loc %wmi %col
scon -r if ($com( $* )) .comclose $*
}
$xtcamp::streamplay By Hixxy
This snippet will let you play streaming audio. It has support for pausing, stopping and streaming playlists amongst other things.
/*
Multi feature version.
Limitations: because mIRC doesn't support COM events I cannot automate the cleanup of objects.
You must do this yourself by using /xtcamp::streamstop <object>, unless you use
the single-feature version at the end of the file.
Requirements: Windows Media Player (not sure which version).
$xtcamp::getstream(<object>)
Returns: the stream that <object> is connected to.
$xtcamp::getstreamstatus(<object>)
Returns: the status of the specified object.
The strings returned from this method are subject to change, but at the time of writing
the strings returned are: "Stopped", "Paused" or "Playing: 128 K bits/second"
(the number 128 can change) without the quotes.
$xtcamp::streamplay(<stream>)
Description: plays audio from a stream. You can also play files on your hard drive.
Returns: an object that should be used with /xtcamp::streamstop.
/xtcamp::playlistexec <object> <command>
Description: performs <command> on each song in a streaming playlist.
The data passed to <command> is "<song> <cr> <URL>" without the quotes.
/xtcamp::setplaylistitem <object> <N>
Description: sets the current item to the Nth item in the playlist.
/xtcamp::streamnext <object>
Description: plays the next song.
/xtcamp::streampause <object>
Description: pauses an audio stream.
/xtcamp::streamprevious <object>
Description: plays the previous song.
/xtcamp::streamresume <object>
Description: resumes a paused audio stream.
/xtcamp::streamstop <object>
Description: stops playing an audio stream and cleans up objects.
Why xtcamp::?
This snippet is part of a much bigger addon.
Feel free to rename the aliases if you wish.
*/
alias xtcamp::getstream {
if ($com($1)) {
!.echo -q $com($1,currentMedia,3,dispatch* $1::currentmedia)
if ($com($1::currentmedia)) {
var %result = $or(,$com($1::currentmedia,sourceURL,3)) $com($1::currentmedia).result
.comclose $1::currentmedia
return %result
}
return $false
}
return $false
}
alias xtcamp::getstreamstatus {
if ($com($1)) return $or(,$com($1,Status,3)) $com($1).result
}
alias xtcamp::playlistexec {
if ($com($1)) && ($com($1::controls)) {
!.echo -q $com($1,currentPlaylist,3,dispatch* $1::playlist)
if ($com($1::playlist)) {
var %count = $or(,$com($1::playlist,Count,3)) $com($1::playlist).result, %item = 0
while (%item < %count) {
!.echo -q $com($1::playlist,item,3,ui4,%item,dispatch* $1::media)
if ($com($1::media)) {
$2- $or(,$com($1::media,Name,3)) $com($1::media).result $cr $or(,$com($1::media,sourceURL,3)) $com($1::media).result
.comclose $1::media
}
inc %item
}
.comclose $1::playlist
}
}
}
alias xtcamp::setplaylistitem {
if ($com($1)) && ($com($1::controls)) {
!.echo -q $com($1,currentPlaylist,3,dispatch* $1::playlist)
if ($com($1::playlist)) {
!.echo -q $com($1::playlist,Count,3)
if ($2 <= $com($1::playlist).result) {
!.echo -q $com($1::playlist,item,3,ui4,$calc($2 - 1),dispatch* $1::media)
if ($com($1::media)) {
!.echo -q $com($1::controls,currentItem,4,dispatch,$1::media)
.comclose $1::media
}
}
.comclose $1::playlist
}
!.echo -q $com($1,Play,3)
}
}
alias xtcamp::streampause {
if ($com($1)) && ($com($1::controls)) !.echo -q $com($1::controls,Pause,3)
}
alias xtcamp::streamnext {
if ($com($1)) && ($com($1::controls)) !.echo -q $com($1::controls,Next,3)
}
alias xtcamp::streamplay {
var %obj = obj $+ $ticks
.comopen %obj WMPlayer.OCX
if ($com(%obj)) {
!.echo -q $com(%obj,Url,4,bstr,$1)
!.echo -q $com(%obj,Controls,3,dispatch* %obj $+ ::controls)
if (!$com(%obj $+ ::controls)) {
.comclose %obj
return $false
}
!.echo -q $com(%obj $+ ::controls,Play,3)
return %obj
}
return $false
}
alias xtcamp::streamprevious {
if ($com($1)) && ($com($1::controls)) !.echo -q $com($1::controls,Previous,3)
}
alias xtcamp::streamresume {
if ($com($1)) && ($com($1::controls)) !.echo -q $com($1::controls,Play,3)
}
alias xtcamp::streamstop {
if ($com($1)) && ($com($1::controls)) {
!.echo -q $com($1::controls,Stop,3)
.comclose $1::controls
.comclose $1
}
}
/*
Single feature version.
This version of the snippet will cleanup objects, but will not let you stop the song or return the
current stream of an object.
Usage: /xtcamp::nstreamplay <stream>
*/
alias xtcamp::nstreamplay {
var %obj = obj $+ $ticks
.comopen %obj WMPlayer.OCX
if ($com(%obj)) {
!.echo -q $com(%obj,Url,4,bstr,$1-)
!.echo -q $com(%obj,Controls,3,dispatch* %obj $+ ::controls)
if (!$com(%obj $+ ::controls)) {
.comclose %obj
return
}
!.echo -q $com(%obj $+ ::controls,Play,3)
.comclose %obj
.comclose %obj $+ ::controls
}
}
/*
Example:
Type /streamex to open an example dialog.
Sorry about the crappy ascii buttons but I'm not going to include a dll with this just for an example dialog.
*/
alias -l add did -a xtcampstreamex 1 $gettok($1-,1,13)
alias streamex dialog -m xtcampstreamex xtcampstreamex
dialog xtcampstreamex {
title "XTCAmp Stream Example"
size -1 -1 229 219
option dbu
list 1, 0 11 229 193, size vsbar
edit "", 2, 0 0 229 10, autohs
check "||", 5, 116 206 25 12, push
button "[]", 6, 90 206 25 12
button "|<<", 7, 38 206 25 12
button "|>", 8, 64 206 25 12
button ">>|", 9, 142 206 25 12
}
on *:dialog:xtcampstreamex:*:*:{
if ($devent == sclick) {
if ($did == 5) {
if (Playing: * iswm $xtcamp::getstreamstatus(%stream)) xtcamp::streampause %stream
else xtcamp::streamresume %stream
}
elseif ($did == 6) {
xtcamp::streamstop %stream
did -r $dname 1
}
elseif ($did == 7) xtcamp::streamprevious %stream
elseif ($did == 8) {
set %stream $xtcamp::streamplay($$did(2))
did -r $dname 1
.timer 1 3 xtcamp::playlistexec %stream add
}
elseif ($did == 9) xtcamp::streamnext %stream
if ($did isnum 6-) did -u $dname 5
}
elseif ($devent $did == dclick 1) {
xtcamp::setplaylistitem %stream $did(1).sel
did -u $dname 5
}
elseif ($devent == close) {
xtcamp::streamstop %stream
unset %stream
}
}